r9739: conver the reg_objects (REGSUBKEY_CTR & REGVAL_CTR) to use
[jra/samba/.git] / source / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-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                 printer->secdesc = dup_sec_desc( get_talloc_ctx(), ntprinter->info_2->secdesc_buf->sec );
4175         }
4176
4177         free_a_printer(&ntprinter, 2);
4178
4179         return True;
4180 }
4181
4182 /********************************************************************
4183  * construct_printer_info_3
4184  * fill a printer_info_3 struct
4185  ********************************************************************/
4186
4187 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4188 {
4189         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4190         PRINTER_INFO_3 *printer = NULL;
4191
4192         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4193                 return False;
4194
4195         *pp_printer = NULL;
4196         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4197                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4198                 return False;
4199         }
4200
4201         ZERO_STRUCTP(printer);
4202         
4203         /* These are the components of the SD we are returning. */
4204
4205         printer->flags = 0x4; 
4206
4207         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4208                 printer->secdesc = dup_sec_desc( get_talloc_ctx(), ntprinter->info_2->secdesc_buf->sec );
4209         }
4210
4211         free_a_printer(&ntprinter, 2);
4212
4213         *pp_printer = printer;
4214         return True;
4215 }
4216
4217 /********************************************************************
4218  * construct_printer_info_4
4219  * fill a printer_info_4 struct
4220  ********************************************************************/
4221
4222 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4223 {
4224         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4225
4226         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4227                 return False;
4228                 
4229         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4230         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4231         printer->attributes = ntprinter->info_2->attributes;
4232
4233         free_a_printer(&ntprinter, 2);
4234         return True;
4235 }
4236
4237 /********************************************************************
4238  * construct_printer_info_5
4239  * fill a printer_info_5 struct
4240  ********************************************************************/
4241
4242 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4243 {
4244         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4245
4246         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4247                 return False;
4248                 
4249         init_unistr(&printer->printername, ntprinter->info_2->printername);
4250         init_unistr(&printer->portname, ntprinter->info_2->portname); 
4251         printer->attributes = ntprinter->info_2->attributes;
4252
4253         /* these two are not used by NT+ according to MSDN */
4254
4255         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4256         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4257
4258         free_a_printer(&ntprinter, 2);
4259
4260         return True;
4261 }
4262
4263 /********************************************************************
4264  * construct_printer_info_7
4265  * fill a printer_info_7 struct
4266  ********************************************************************/
4267
4268 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4269 {
4270         char *guid_str = NULL;
4271         struct uuid guid; 
4272         
4273         if (is_printer_published(print_hnd, snum, &guid)) {
4274                 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4275                 strupper_m(guid_str);
4276                 init_unistr(&printer->guid, guid_str);
4277                 printer->action = SPOOL_DS_PUBLISH;
4278         } else {
4279                 init_unistr(&printer->guid, "");
4280                 printer->action = SPOOL_DS_UNPUBLISH;
4281         }
4282
4283         return True;
4284 }
4285
4286 /********************************************************************
4287  Spoolss_enumprinters.
4288 ********************************************************************/
4289
4290 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4291 {
4292         int snum;
4293         int i;
4294         int n_services=lp_numservices();
4295         PRINTER_INFO_1 *tp, *printers=NULL;
4296         PRINTER_INFO_1 current_prt;
4297         WERROR result = WERR_OK;
4298         
4299         DEBUG(4,("enum_all_printers_info_1\n"));        
4300
4301         for (snum=0; snum<n_services; snum++) {
4302                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4303                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4304
4305                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4306                                 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4307                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4308                                         SAFE_FREE(printers);
4309                                         *returned=0;
4310                                         return WERR_NOMEM;
4311                                 }
4312                                 else printers = tp;
4313                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
4314
4315                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4316                                 (*returned)++;
4317                         }
4318                 }
4319         }
4320                 
4321         /* check the required size. */  
4322         for (i=0; i<*returned; i++)
4323                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4324
4325         if (*needed > offered) {
4326                 result = WERR_INSUFFICIENT_BUFFER;
4327                 goto out;
4328         }
4329
4330         if (!rpcbuf_alloc_size(buffer, *needed)) {
4331                 result = WERR_NOMEM;
4332                 goto out;
4333         }
4334
4335         /* fill the buffer with the structures */
4336         for (i=0; i<*returned; i++)
4337                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
4338
4339 out:
4340         /* clear memory */
4341
4342         SAFE_FREE(printers);
4343
4344         if ( !W_ERROR_IS_OK(result) )
4345                 *returned = 0;
4346
4347         return result;
4348 }
4349
4350 /********************************************************************
4351  enum_all_printers_info_1_local.
4352 *********************************************************************/
4353
4354 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4355 {
4356         DEBUG(4,("enum_all_printers_info_1_local\n"));  
4357         
4358         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4359 }
4360
4361 /********************************************************************
4362  enum_all_printers_info_1_name.
4363 *********************************************************************/
4364
4365 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4366 {
4367         char *s = name;
4368         
4369         DEBUG(4,("enum_all_printers_info_1_name\n"));   
4370         
4371         if ((name[0] == '\\') && (name[1] == '\\'))
4372                 s = name + 2;
4373                 
4374         if (is_myname_or_ipaddr(s)) {
4375                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4376         }
4377         else
4378                 return WERR_INVALID_NAME;
4379 }
4380
4381 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4382 /********************************************************************
4383  enum_all_printers_info_1_remote.
4384 *********************************************************************/
4385
4386 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4387 {
4388         PRINTER_INFO_1 *printer;
4389         fstring printername;
4390         fstring desc;
4391         fstring comment;
4392         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
4393         WERROR result = WERR_OK;
4394
4395         /* JFM: currently it's more a place holder than anything else.
4396          * In the spooler world there is a notion of server registration.
4397          * the print servers are registered on the PDC (in the same domain)
4398          *
4399          * We should have a TDB here. The registration is done thru an 
4400          * undocumented RPC call.
4401          */
4402         
4403         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4404                 return WERR_NOMEM;
4405
4406         *returned=1;
4407         
4408         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);                
4409         slprintf(desc, sizeof(desc)-1,"%s", name);
4410         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4411
4412         init_unistr(&printer->description, desc);
4413         init_unistr(&printer->name, printername);       
4414         init_unistr(&printer->comment, comment);
4415         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4416                 
4417         /* check the required size. */  
4418         *needed += spoolss_size_printer_info_1(printer);
4419
4420         if (*needed > offered) {
4421                 result = WERR_INSUFFICIENT_BUFFER;
4422                 goto out;
4423         }
4424
4425         if (!rpcbuf_alloc_size(buffer, *needed)) {
4426                 result = WERR_NOMEM;
4427                 goto out;
4428         }
4429
4430         /* fill the buffer with the structures */
4431         smb_io_printer_info_1("", buffer, printer, 0);  
4432
4433 out:
4434         /* clear memory */
4435         SAFE_FREE(printer);
4436
4437         if ( !W_ERROR_IS_OK(result) )
4438                 *returned = 0;
4439
4440         return result;
4441 }
4442
4443 #endif
4444
4445 /********************************************************************
4446  enum_all_printers_info_1_network.
4447 *********************************************************************/
4448
4449 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4450 {
4451         char *s = name;
4452
4453         DEBUG(4,("enum_all_printers_info_1_network\n"));        
4454         
4455         /* If we respond to a enum_printers level 1 on our name with flags
4456            set to PRINTER_ENUM_REMOTE with a list of printers then these
4457            printers incorrectly appear in the APW browse list.
4458            Specifically the printers for the server appear at the workgroup
4459            level where all the other servers in the domain are
4460            listed. Windows responds to this call with a
4461            WERR_CAN_NOT_COMPLETE so we should do the same. */ 
4462
4463         if (name[0] == '\\' && name[1] == '\\')
4464                  s = name + 2;
4465
4466         if (is_myname_or_ipaddr(s))
4467                  return WERR_CAN_NOT_COMPLETE;
4468
4469         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4470 }
4471
4472 /********************************************************************
4473  * api_spoolss_enumprinters
4474  *
4475  * called from api_spoolss_enumprinters (see this to understand)
4476  ********************************************************************/
4477
4478 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4479 {
4480         int snum;
4481         int i;
4482         int n_services=lp_numservices();
4483         PRINTER_INFO_2 *tp, *printers=NULL;
4484         PRINTER_INFO_2 current_prt;
4485         WERROR result = WERR_OK;
4486
4487         for (snum=0; snum<n_services; snum++) {
4488                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4489                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4490                                 
4491                         if (construct_printer_info_2(NULL, &current_prt, snum)) 
4492                         {
4493                                 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4494                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4495                                         SAFE_FREE(printers);
4496                                         *returned = 0;
4497                                         return WERR_NOMEM;
4498                                 }
4499
4500                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
4501
4502                                 printers = tp;
4503                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4504
4505                                 (*returned)++;
4506                         }
4507                 }
4508         }
4509         
4510         /* check the required size. */  
4511         for (i=0; i<*returned; i++) 
4512                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4513         
4514         if (*needed > offered) {
4515                 result = WERR_INSUFFICIENT_BUFFER;
4516                 goto out;
4517         }
4518
4519         if (!rpcbuf_alloc_size(buffer, *needed)) {
4520                 result = WERR_NOMEM;
4521                 goto out;
4522         }
4523
4524         /* fill the buffer with the structures */
4525         for (i=0; i<*returned; i++)
4526                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
4527         
4528 out:
4529         /* clear memory */
4530
4531         for (i=0; i<*returned; i++) 
4532                 free_devmode(printers[i].devmode);
4533
4534         SAFE_FREE(printers);
4535
4536         if ( !W_ERROR_IS_OK(result) )
4537                 *returned = 0;
4538
4539         return result;
4540 }
4541
4542 /********************************************************************
4543  * handle enumeration of printers at level 1
4544  ********************************************************************/
4545
4546 static WERROR enumprinters_level1( uint32 flags, fstring name,
4547                                  RPC_BUFFER *buffer, uint32 offered,
4548                                  uint32 *needed, uint32 *returned)
4549 {
4550         /* Not all the flags are equals */
4551
4552         if (flags & PRINTER_ENUM_LOCAL)
4553                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4554
4555         if (flags & PRINTER_ENUM_NAME)
4556                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4557
4558 #if 0   /* JERRY - disabled for now */
4559         if (flags & PRINTER_ENUM_REMOTE)
4560                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4561 #endif
4562
4563         if (flags & PRINTER_ENUM_NETWORK)
4564                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4565
4566         return WERR_OK; /* NT4sp5 does that */
4567 }
4568
4569 /********************************************************************
4570  * handle enumeration of printers at level 2
4571  ********************************************************************/
4572
4573 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4574                                  RPC_BUFFER *buffer, uint32 offered,
4575                                  uint32 *needed, uint32 *returned)
4576 {
4577         char *s = servername;
4578
4579         if (flags & PRINTER_ENUM_LOCAL) {
4580                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4581         }
4582
4583         if (flags & PRINTER_ENUM_NAME) {
4584                 if ((servername[0] == '\\') && (servername[1] == '\\'))
4585                         s = servername + 2;
4586                 if (is_myname_or_ipaddr(s))
4587                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4588                 else
4589                         return WERR_INVALID_NAME;
4590         }
4591
4592         if (flags & PRINTER_ENUM_REMOTE)
4593                 return WERR_UNKNOWN_LEVEL;
4594
4595         return WERR_OK;
4596 }
4597
4598 /********************************************************************
4599  * handle enumeration of printers at level 5
4600  ********************************************************************/
4601
4602 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4603                                  RPC_BUFFER *buffer, uint32 offered,
4604                                  uint32 *needed, uint32 *returned)
4605 {
4606 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4607         return WERR_OK;
4608 }
4609
4610 /********************************************************************
4611  * api_spoolss_enumprinters
4612  *
4613  * called from api_spoolss_enumprinters (see this to understand)
4614  ********************************************************************/
4615
4616 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4617 {
4618         uint32 flags = q_u->flags;
4619         UNISTR2 *servername = &q_u->servername;
4620         uint32 level = q_u->level;
4621         RPC_BUFFER *buffer = NULL;
4622         uint32 offered = q_u->offered;
4623         uint32 *needed = &r_u->needed;
4624         uint32 *returned = &r_u->returned;
4625
4626         fstring name;
4627         
4628         /* that's an [in out] buffer */
4629
4630         if ( q_u->buffer ) {
4631                 rpcbuf_move(q_u->buffer, &r_u->buffer);
4632                 buffer = r_u->buffer;
4633         }
4634
4635         DEBUG(4,("_spoolss_enumprinters\n"));
4636
4637         *needed=0;
4638         *returned=0;
4639         
4640         /*
4641          * Level 1:
4642          *          flags==PRINTER_ENUM_NAME
4643          *           if name=="" then enumerates all printers
4644          *           if name!="" then enumerate the printer
4645          *          flags==PRINTER_ENUM_REMOTE
4646          *          name is NULL, enumerate printers
4647          * Level 2: name!="" enumerates printers, name can't be NULL
4648          * Level 3: doesn't exist
4649          * Level 4: does a local registry lookup
4650          * Level 5: same as Level 2
4651          */
4652
4653         unistr2_to_ascii(name, servername, sizeof(name)-1);
4654         strupper_m(name);
4655
4656         switch (level) {
4657         case 1:
4658                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4659         case 2:
4660                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4661         case 5:
4662                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4663         case 3:
4664         case 4:
4665                 break;
4666         }
4667         return WERR_UNKNOWN_LEVEL;
4668 }
4669
4670 /****************************************************************************
4671 ****************************************************************************/
4672
4673 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4674 {
4675         PRINTER_INFO_0 *printer=NULL;
4676         WERROR result = WERR_OK;
4677
4678         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4679                 return WERR_NOMEM;
4680
4681         construct_printer_info_0(print_hnd, printer, snum);
4682         
4683         /* check the required size. */  
4684         *needed += spoolss_size_printer_info_0(printer);
4685
4686         if (*needed > offered) {
4687                 result = WERR_INSUFFICIENT_BUFFER;
4688                 goto out;
4689         }
4690
4691         if (!rpcbuf_alloc_size(buffer, *needed)) {
4692                 result = WERR_NOMEM;
4693                 goto out;
4694         }
4695
4696         /* fill the buffer with the structures */
4697         smb_io_printer_info_0("", buffer, printer, 0);  
4698         
4699 out:
4700         /* clear memory */
4701
4702         SAFE_FREE(printer);
4703
4704         return result;
4705 }
4706
4707 /****************************************************************************
4708 ****************************************************************************/
4709
4710 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4711 {
4712         PRINTER_INFO_1 *printer=NULL;
4713         WERROR result = WERR_OK;
4714
4715         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4716                 return WERR_NOMEM;
4717
4718         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4719         
4720         /* check the required size. */  
4721         *needed += spoolss_size_printer_info_1(printer);
4722
4723         if (*needed > offered) {
4724                 result = WERR_INSUFFICIENT_BUFFER;
4725                 goto out;
4726         }
4727
4728         if (!rpcbuf_alloc_size(buffer, *needed)) {
4729                 result = WERR_NOMEM;
4730                 goto out;
4731         }
4732
4733         /* fill the buffer with the structures */
4734         smb_io_printer_info_1("", buffer, printer, 0);  
4735         
4736 out:
4737         /* clear memory */
4738         SAFE_FREE(printer);
4739
4740         return result;  
4741 }
4742
4743 /****************************************************************************
4744 ****************************************************************************/
4745
4746 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4747 {
4748         PRINTER_INFO_2 *printer=NULL;
4749         WERROR result = WERR_OK;
4750
4751         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4752                 return WERR_NOMEM;
4753         
4754         construct_printer_info_2(print_hnd, printer, snum);
4755         
4756         /* check the required size. */  
4757         *needed += spoolss_size_printer_info_2(printer);
4758         
4759         if (*needed > offered) {
4760                 result = WERR_INSUFFICIENT_BUFFER;
4761                 goto out;
4762         }
4763
4764         if (!rpcbuf_alloc_size(buffer, *needed)) {
4765                 result = WERR_NOMEM;
4766                 goto out;
4767         }
4768
4769         /* fill the buffer with the structures */
4770         if (!smb_io_printer_info_2("", buffer, printer, 0)) 
4771                 result = WERR_NOMEM;
4772         
4773 out:
4774         /* clear memory */
4775         free_printer_info_2(printer);
4776
4777         return result;  
4778 }
4779
4780 /****************************************************************************
4781 ****************************************************************************/
4782
4783 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4784 {
4785         PRINTER_INFO_3 *printer=NULL;
4786         WERROR result = WERR_OK;
4787
4788         if (!construct_printer_info_3(print_hnd, &printer, snum))
4789                 return WERR_NOMEM;
4790         
4791         /* check the required size. */  
4792         *needed += spoolss_size_printer_info_3(printer);
4793
4794         if (*needed > offered) {
4795                 result = WERR_INSUFFICIENT_BUFFER;
4796                 goto out;
4797         }
4798
4799         if (!rpcbuf_alloc_size(buffer, *needed)) {
4800                 result = WERR_NOMEM;
4801                 goto out;
4802         }
4803
4804         /* fill the buffer with the structures */
4805         smb_io_printer_info_3("", buffer, printer, 0);  
4806         
4807 out:
4808         /* clear memory */
4809         free_printer_info_3(printer);
4810         
4811         return result;  
4812 }
4813
4814 /****************************************************************************
4815 ****************************************************************************/
4816
4817 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4818 {
4819         PRINTER_INFO_4 *printer=NULL;
4820         WERROR result = WERR_OK;
4821
4822         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4823                 return WERR_NOMEM;
4824
4825         if (!construct_printer_info_4(print_hnd, printer, snum))
4826                 return WERR_NOMEM;
4827         
4828         /* check the required size. */  
4829         *needed += spoolss_size_printer_info_4(printer);
4830
4831         if (*needed > offered) {
4832                 result = WERR_INSUFFICIENT_BUFFER;
4833                 goto out;
4834         }
4835
4836         if (!rpcbuf_alloc_size(buffer, *needed)) {
4837                 result = WERR_NOMEM;
4838                 goto out;
4839         }
4840
4841         /* fill the buffer with the structures */
4842         smb_io_printer_info_4("", buffer, printer, 0);  
4843         
4844 out:
4845         /* clear memory */
4846         free_printer_info_4(printer);
4847         
4848         return result;  
4849 }
4850
4851 /****************************************************************************
4852 ****************************************************************************/
4853
4854 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4855 {
4856         PRINTER_INFO_5 *printer=NULL;
4857         WERROR result = WERR_OK;
4858
4859         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4860                 return WERR_NOMEM;
4861
4862         if (!construct_printer_info_5(print_hnd, printer, snum))
4863                 return WERR_NOMEM;
4864         
4865         /* check the required size. */  
4866         *needed += spoolss_size_printer_info_5(printer);
4867
4868         if (*needed > offered) {
4869                 result = WERR_INSUFFICIENT_BUFFER;
4870                 goto out;
4871         }
4872
4873         if (!rpcbuf_alloc_size(buffer, *needed)) {
4874                 result = WERR_NOMEM;
4875                 goto out;
4876         }
4877
4878         /* fill the buffer with the structures */
4879         smb_io_printer_info_5("", buffer, printer, 0);  
4880         
4881 out:
4882         /* clear memory */
4883         free_printer_info_5(printer);
4884         
4885         return result;  
4886 }
4887
4888 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 {
4890         PRINTER_INFO_7 *printer=NULL;
4891         WERROR result = WERR_OK;
4892
4893         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4894                 return WERR_NOMEM;
4895
4896         if (!construct_printer_info_7(print_hnd, printer, snum))
4897                 return WERR_NOMEM;
4898         
4899         /* check the required size. */  
4900         *needed += spoolss_size_printer_info_7(printer);
4901
4902         if (*needed > offered) {
4903                 result = WERR_INSUFFICIENT_BUFFER;
4904                 goto out;
4905         }
4906
4907         if (!rpcbuf_alloc_size(buffer, *needed)) {
4908                 result = WERR_NOMEM;
4909                 goto out;
4910
4911         }
4912
4913         /* fill the buffer with the structures */
4914         smb_io_printer_info_7("", buffer, printer, 0);  
4915         
4916 out:
4917         /* clear memory */
4918         free_printer_info_7(printer);
4919         
4920         return result;  
4921 }
4922
4923 /****************************************************************************
4924 ****************************************************************************/
4925
4926 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4927 {
4928         POLICY_HND *handle = &q_u->handle;
4929         uint32 level = q_u->level;
4930         RPC_BUFFER *buffer = NULL;
4931         uint32 offered = q_u->offered;
4932         uint32 *needed = &r_u->needed;
4933         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4934
4935         int snum;
4936
4937         /* that's an [in out] buffer */
4938
4939         if ( q_u->buffer ) {
4940                 rpcbuf_move(q_u->buffer, &r_u->buffer);
4941                 buffer = r_u->buffer;
4942         }
4943
4944         *needed=0;
4945
4946         if (!get_printer_snum(p, handle, &snum))
4947                 return WERR_BADFID;
4948
4949         switch (level) {
4950         case 0:
4951                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4952         case 1:
4953                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4954         case 2:         
4955                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4956         case 3:         
4957                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4958         case 4:         
4959                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4960         case 5:         
4961                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4962         case 7:
4963                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4964         }
4965         return WERR_UNKNOWN_LEVEL;
4966 }       
4967                 
4968 /********************************************************************
4969  * fill a DRIVER_INFO_1 struct
4970  ********************************************************************/
4971
4972 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4973 {
4974         init_unistr( &info->name, driver.info_3->name);
4975 }
4976
4977 /********************************************************************
4978  * construct_printer_driver_info_1
4979  ********************************************************************/
4980
4981 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4982 {       
4983         NT_PRINTER_INFO_LEVEL *printer = NULL;
4984         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4985
4986         ZERO_STRUCT(driver);
4987
4988         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4989                 return WERR_INVALID_PRINTER_NAME;
4990
4991         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4992                 return WERR_UNKNOWN_PRINTER_DRIVER;
4993
4994         fill_printer_driver_info_1(info, driver, servername, architecture);
4995
4996         free_a_printer(&printer,2);
4997
4998         return WERR_OK;
4999 }
5000
5001 /********************************************************************
5002  * construct_printer_driver_info_2
5003  * fill a printer_info_2 struct
5004  ********************************************************************/
5005
5006 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5007 {
5008         pstring temp;
5009
5010         info->version=driver.info_3->cversion;
5011
5012         init_unistr( &info->name, driver.info_3->name );
5013         init_unistr( &info->architecture, driver.info_3->environment );
5014
5015
5016     if (strlen(driver.info_3->driverpath)) {
5017                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5018                 init_unistr( &info->driverpath, temp );
5019     } else
5020         init_unistr( &info->driverpath, "" );
5021
5022         if (strlen(driver.info_3->datafile)) {
5023                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5024                 init_unistr( &info->datafile, temp );
5025         } else
5026                 init_unistr( &info->datafile, "" );
5027         
5028         if (strlen(driver.info_3->configfile)) {
5029                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5030                 init_unistr( &info->configfile, temp ); 
5031         } else
5032                 init_unistr( &info->configfile, "" );
5033 }
5034
5035 /********************************************************************
5036  * construct_printer_driver_info_2
5037  * fill a printer_info_2 struct
5038  ********************************************************************/
5039
5040 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5041 {
5042         NT_PRINTER_INFO_LEVEL *printer = NULL;
5043         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5044
5045         ZERO_STRUCT(printer);
5046         ZERO_STRUCT(driver);
5047
5048         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5049                 return WERR_INVALID_PRINTER_NAME;
5050
5051         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5052                 return WERR_UNKNOWN_PRINTER_DRIVER;
5053
5054         fill_printer_driver_info_2(info, driver, servername);
5055
5056         free_a_printer(&printer,2);
5057
5058         return WERR_OK;
5059 }
5060
5061 /********************************************************************
5062  * copy a strings array and convert to UNICODE
5063  *
5064  * convert an array of ascii string to a UNICODE string
5065  ********************************************************************/
5066
5067 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5068 {
5069         int i=0;
5070         int j=0;
5071         const char *v;
5072         pstring line;
5073         uint16 *tuary;
5074
5075         DEBUG(6,("init_unistr_array\n"));
5076         *uni_array=NULL;
5077
5078         while (True) 
5079         {
5080                 if ( !char_array )
5081                         v = "";
5082                 else 
5083                 {
5084                         v = char_array[i];
5085                         if (!v) 
5086                                 v = ""; /* hack to handle null lists */
5087                 }
5088                 
5089                 /* hack to allow this to be used in places other than when generating 
5090                    the list of dependent files */
5091                    
5092                 if ( servername )
5093                         slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5094                 else
5095                         pstrcpy( line, v );
5096                         
5097                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5098
5099                 /* add one extra unit16 for the second terminating NULL */
5100                 
5101                 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5102                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5103                         return 0;
5104                 } else
5105                         *uni_array = tuary;
5106                         
5107                 if ( !strlen(v) ) 
5108                         break;
5109                 
5110                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5111                 i++;
5112         }
5113         
5114         if (*uni_array) {
5115                 /* special case for ""; we need to add both NULL's here */
5116                 if (!j)
5117                         (*uni_array)[j++]=0x0000;       
5118                 (*uni_array)[j]=0x0000;
5119         }
5120         
5121         DEBUGADD(6,("last one:done\n"));
5122
5123         /* return size of array in uint16's */
5124                 
5125         return j+1;
5126 }
5127
5128 /********************************************************************
5129  * construct_printer_info_3
5130  * fill a printer_info_3 struct
5131  ********************************************************************/
5132
5133 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5134 {
5135         pstring temp;
5136
5137         ZERO_STRUCTP(info);
5138
5139         info->version=driver.info_3->cversion;
5140
5141         init_unistr( &info->name, driver.info_3->name );        
5142         init_unistr( &info->architecture, driver.info_3->environment );
5143
5144         if (strlen(driver.info_3->driverpath)) {
5145                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5146                 init_unistr( &info->driverpath, temp );
5147         } else
5148                 init_unistr( &info->driverpath, "" );
5149     
5150         if (strlen(driver.info_3->datafile)) {
5151                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5152                 init_unistr( &info->datafile, temp );
5153         } else
5154                 init_unistr( &info->datafile, "" );
5155
5156         if (strlen(driver.info_3->configfile)) {
5157                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5158                 init_unistr( &info->configfile, temp ); 
5159         } else
5160                 init_unistr( &info->configfile, "" );
5161
5162         if (strlen(driver.info_3->helpfile)) {
5163                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5164                 init_unistr( &info->helpfile, temp );
5165         } else
5166                 init_unistr( &info->helpfile, "" );
5167
5168         init_unistr( &info->monitorname, driver.info_3->monitorname );
5169         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5170
5171         info->dependentfiles=NULL;
5172         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5173 }
5174
5175 /********************************************************************
5176  * construct_printer_info_3
5177  * fill a printer_info_3 struct
5178  ********************************************************************/
5179
5180 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5181 {       
5182         NT_PRINTER_INFO_LEVEL *printer = NULL;
5183         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5184         WERROR status;
5185         ZERO_STRUCT(driver);
5186
5187         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5188         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5189         if (!W_ERROR_IS_OK(status))
5190                 return WERR_INVALID_PRINTER_NAME;
5191
5192         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5193         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194
5195 #if 0   /* JERRY */
5196
5197         /* 
5198          * I put this code in during testing.  Helpful when commenting out the 
5199          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5200          * as win2k always queries the driver using an infor level of 6.
5201          * I've left it in (but ifdef'd out) because I'll probably
5202          * use it in experimentation again in the future.   --jerry 22/01/2002
5203          */
5204
5205         if (!W_ERROR_IS_OK(status)) {
5206                 /*
5207                  * Is this a W2k client ?
5208                  */
5209                 if (version == 3) {
5210                         /* Yes - try again with a WinNT driver. */
5211                         version = 2;
5212                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5213                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5214                 }
5215 #endif
5216
5217                 if (!W_ERROR_IS_OK(status)) {
5218                         free_a_printer(&printer,2);
5219                         return WERR_UNKNOWN_PRINTER_DRIVER;
5220                 }
5221                 
5222 #if 0   /* JERRY */
5223         }
5224 #endif
5225         
5226
5227         fill_printer_driver_info_3(info, driver, servername);
5228
5229         free_a_printer(&printer,2);
5230
5231         return WERR_OK;
5232 }
5233
5234 /********************************************************************
5235  * construct_printer_info_6
5236  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5237  ********************************************************************/
5238
5239 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5240 {
5241         pstring temp;
5242         fstring nullstr;
5243
5244         ZERO_STRUCTP(info);
5245         memset(&nullstr, '\0', sizeof(fstring));
5246
5247         info->version=driver.info_3->cversion;
5248
5249         init_unistr( &info->name, driver.info_3->name );        
5250         init_unistr( &info->architecture, driver.info_3->environment );
5251
5252         if (strlen(driver.info_3->driverpath)) {
5253                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5254                 init_unistr( &info->driverpath, temp );
5255         } else
5256                 init_unistr( &info->driverpath, "" );
5257
5258         if (strlen(driver.info_3->datafile)) {
5259                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5260                 init_unistr( &info->datafile, temp );
5261         } else
5262                 init_unistr( &info->datafile, "" );
5263
5264         if (strlen(driver.info_3->configfile)) {
5265                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5266                 init_unistr( &info->configfile, temp ); 
5267         } else
5268                 init_unistr( &info->configfile, "" );
5269
5270         if (strlen(driver.info_3->helpfile)) {
5271                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5272                 init_unistr( &info->helpfile, temp );
5273         } else
5274                 init_unistr( &info->helpfile, "" );
5275         
5276         init_unistr( &info->monitorname, driver.info_3->monitorname );
5277         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5278
5279         info->dependentfiles = NULL;
5280         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5281
5282         info->previousdrivernames=NULL;
5283         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5284
5285         info->driver_date.low=0;
5286         info->driver_date.high=0;
5287
5288         info->padding=0;
5289         info->driver_version_low=0;
5290         info->driver_version_high=0;
5291
5292         init_unistr( &info->mfgname, "");
5293         init_unistr( &info->oem_url, "");
5294         init_unistr( &info->hardware_id, "");
5295         init_unistr( &info->provider, "");
5296 }
5297
5298 /********************************************************************
5299  * construct_printer_info_6
5300  * fill a printer_info_6 struct
5301  ********************************************************************/
5302
5303 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, 
5304               fstring servername, fstring architecture, uint32 version)
5305 {       
5306         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5307         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5308         WERROR                          status;
5309         
5310         ZERO_STRUCT(driver);
5311
5312         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5313         
5314         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5315         
5316         if (!W_ERROR_IS_OK(status))
5317                 return WERR_INVALID_PRINTER_NAME;
5318
5319         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5320                 
5321         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5322         
5323         if (!W_ERROR_IS_OK(status)) 
5324         {
5325                 /*
5326                  * Is this a W2k client ?
5327                  */
5328
5329                 if (version < 3) {
5330                         free_a_printer(&printer,2);
5331                         return WERR_UNKNOWN_PRINTER_DRIVER;
5332                 }
5333
5334                 /* Yes - try again with a WinNT driver. */
5335                 version = 2;
5336                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5337                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338                 if (!W_ERROR_IS_OK(status)) {
5339                         free_a_printer(&printer,2);
5340                         return WERR_UNKNOWN_PRINTER_DRIVER;
5341                 }
5342         }
5343
5344         fill_printer_driver_info_6(info, driver, servername);
5345
5346         free_a_printer(&printer,2);
5347         free_a_printer_driver(driver, 3);
5348
5349         return WERR_OK;
5350 }
5351
5352 /****************************************************************************
5353 ****************************************************************************/
5354
5355 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5356 {
5357         SAFE_FREE(info->dependentfiles);
5358 }
5359
5360 /****************************************************************************
5361 ****************************************************************************/
5362
5363 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5364 {
5365         SAFE_FREE(info->dependentfiles);
5366 }
5367
5368 /****************************************************************************
5369 ****************************************************************************/
5370
5371 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5372 {
5373         DRIVER_INFO_1 *info=NULL;
5374         WERROR result;
5375         
5376         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5377                 return WERR_NOMEM;
5378         
5379         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5380         if (!W_ERROR_IS_OK(result)) 
5381                 goto out;
5382
5383         /* check the required size. */  
5384         *needed += spoolss_size_printer_driver_info_1(info);
5385
5386         if (*needed > offered) {
5387                 result = WERR_INSUFFICIENT_BUFFER;
5388                 goto out;
5389         }
5390
5391         if (!rpcbuf_alloc_size(buffer, *needed)) {
5392                 result = WERR_NOMEM;
5393                 goto out;
5394         }
5395
5396         /* fill the buffer with the structures */
5397         smb_io_printer_driver_info_1("", buffer, info, 0);      
5398
5399 out:
5400         /* clear memory */
5401         SAFE_FREE(info);
5402
5403         return result;
5404 }
5405
5406 /****************************************************************************
5407 ****************************************************************************/
5408
5409 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5410 {
5411         DRIVER_INFO_2 *info=NULL;
5412         WERROR result;
5413         
5414         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5415                 return WERR_NOMEM;
5416         
5417         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5418         if (!W_ERROR_IS_OK(result)) 
5419                 goto out;
5420
5421         /* check the required size. */  
5422         *needed += spoolss_size_printer_driver_info_2(info);
5423
5424         if (*needed > offered) {
5425                 result = WERR_INSUFFICIENT_BUFFER;
5426                 goto out;
5427         }
5428         
5429         if (!rpcbuf_alloc_size(buffer, *needed)) {
5430                 result = WERR_NOMEM;
5431                 goto out;
5432         }
5433
5434         /* fill the buffer with the structures */
5435         smb_io_printer_driver_info_2("", buffer, info, 0);      
5436
5437 out:
5438         /* clear memory */
5439         SAFE_FREE(info);
5440
5441         return result;
5442 }
5443
5444 /****************************************************************************
5445 ****************************************************************************/
5446
5447 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5448 {
5449         DRIVER_INFO_3 info;
5450         WERROR result;
5451
5452         ZERO_STRUCT(info);
5453
5454         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5455         if (!W_ERROR_IS_OK(result))
5456                 goto out;
5457
5458         /* check the required size. */  
5459         *needed += spoolss_size_printer_driver_info_3(&info);
5460
5461         if (*needed > offered) {
5462                 result = WERR_INSUFFICIENT_BUFFER;
5463                 goto out;
5464         }
5465
5466         if (!rpcbuf_alloc_size(buffer, *needed)) {
5467                 result = WERR_NOMEM;
5468                 goto out;
5469         }
5470
5471         /* fill the buffer with the structures */
5472         smb_io_printer_driver_info_3("", buffer, &info, 0);
5473
5474 out:
5475         free_printer_driver_info_3(&info);
5476
5477         return result;
5478 }
5479
5480 /****************************************************************************
5481 ****************************************************************************/
5482
5483 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5484 {
5485         DRIVER_INFO_6 info;
5486         WERROR result;
5487
5488         ZERO_STRUCT(info);
5489
5490         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5491         if (!W_ERROR_IS_OK(result)) 
5492                 goto out;
5493
5494         /* check the required size. */  
5495         *needed += spoolss_size_printer_driver_info_6(&info);
5496
5497         if (*needed > offered) {
5498                 result = WERR_INSUFFICIENT_BUFFER;
5499                 goto out;
5500         }
5501         
5502         if (!rpcbuf_alloc_size(buffer, *needed)) {
5503                 result = WERR_NOMEM;
5504                 goto out;
5505         }
5506
5507         /* fill the buffer with the structures */
5508         smb_io_printer_driver_info_6("", buffer, &info, 0);
5509
5510 out:
5511         free_printer_driver_info_6(&info);
5512
5513         return result;
5514 }
5515
5516 /****************************************************************************
5517 ****************************************************************************/
5518
5519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5520 {
5521         POLICY_HND *handle = &q_u->handle;
5522         UNISTR2 *uni_arch = &q_u->architecture;
5523         uint32 level = q_u->level;
5524         uint32 clientmajorversion = q_u->clientmajorversion;
5525         RPC_BUFFER *buffer = NULL;
5526         uint32 offered = q_u->offered;
5527         uint32 *needed = &r_u->needed;
5528         uint32 *servermajorversion = &r_u->servermajorversion;
5529         uint32 *serverminorversion = &r_u->serverminorversion;
5530         Printer_entry *printer;
5531
5532         fstring servername;
5533         fstring architecture;
5534         int snum;
5535
5536         /* that's an [in out] buffer */
5537
5538         if ( q_u->buffer ) {
5539                 rpcbuf_move(q_u->buffer, &r_u->buffer);
5540                 buffer = r_u->buffer;
5541         }
5542
5543         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5544
5545         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5546                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5547                 return WERR_INVALID_PRINTER_NAME;
5548         }
5549
5550         *needed = 0;
5551         *servermajorversion = 0;
5552         *serverminorversion = 0;
5553
5554         fstrcpy(servername, get_server_name( printer ));
5555         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5556
5557         if (!get_printer_snum(p, handle, &snum))
5558                 return WERR_BADFID;
5559
5560         switch (level) {
5561         case 1:
5562                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563         case 2:
5564                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565         case 3:
5566                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5567         case 6:
5568                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5569 #if 0   /* JERRY */
5570         case 101: 
5571                 /* apparently this call is the equivalent of 
5572                    EnumPrinterDataEx() for the DsDriver key */
5573                 break;
5574 #endif
5575         }
5576
5577         return WERR_UNKNOWN_LEVEL;
5578 }
5579
5580 /****************************************************************************
5581 ****************************************************************************/
5582
5583 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5584 {
5585         POLICY_HND *handle = &q_u->handle;
5586
5587         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5588
5589         if (!Printer) {
5590                 DEBUG(3,("Error in startpageprinter printer handle\n"));
5591                 return WERR_BADFID;
5592         }
5593
5594         Printer->page_started=True;
5595         return WERR_OK;
5596 }
5597
5598 /****************************************************************************
5599 ****************************************************************************/
5600
5601 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5602 {
5603         POLICY_HND *handle = &q_u->handle;
5604         int snum;
5605
5606         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5607
5608         if (!Printer) {
5609                 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5610                 return WERR_BADFID;
5611         }
5612         
5613         if (!get_printer_snum(p, handle, &snum))
5614                 return WERR_BADFID;
5615
5616         Printer->page_started=False;
5617         print_job_endpage(snum, Printer->jobid);
5618
5619         return WERR_OK;
5620 }
5621
5622 /********************************************************************
5623  * api_spoolss_getprinter
5624  * called from the spoolss dispatcher
5625  *
5626  ********************************************************************/
5627
5628 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5629 {
5630         POLICY_HND *handle = &q_u->handle;
5631         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5632         uint32 *jobid = &r_u->jobid;
5633
5634         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5635         int snum;
5636         pstring jobname;
5637         fstring datatype;
5638         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5639         struct current_user user;
5640
5641         if (!Printer) {
5642                 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5643                 return WERR_BADFID;
5644         }
5645
5646         get_current_user(&user, p);
5647
5648         /*
5649          * a nice thing with NT is it doesn't listen to what you tell it.
5650          * when asked to send _only_ RAW datas, it tries to send datas
5651          * in EMF format.
5652          *
5653          * So I add checks like in NT Server ...
5654          */
5655         
5656         if (info_1->p_datatype != 0) {
5657                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5658                 if (strcmp(datatype, "RAW") != 0) {
5659                         (*jobid)=0;
5660                         return WERR_INVALID_DATATYPE;
5661                 }               
5662         }               
5663         
5664         /* get the share number of the printer */
5665         if (!get_printer_snum(p, handle, &snum)) {
5666                 return WERR_BADFID;
5667         }
5668
5669         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5670         
5671         Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5672
5673         /* An error occured in print_job_start() so return an appropriate
5674            NT error code. */
5675
5676         if (Printer->jobid == -1) {
5677                 return map_werror_from_unix(errno);
5678         }
5679         
5680         Printer->document_started=True;
5681         (*jobid) = Printer->jobid;
5682
5683         return WERR_OK;
5684 }
5685
5686 /********************************************************************
5687  * api_spoolss_getprinter
5688  * called from the spoolss dispatcher
5689  *
5690  ********************************************************************/
5691
5692 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5693 {
5694         POLICY_HND *handle = &q_u->handle;
5695
5696         return _spoolss_enddocprinter_internal(p, handle);
5697 }
5698
5699 /****************************************************************************
5700 ****************************************************************************/
5701
5702 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5703 {
5704         POLICY_HND *handle = &q_u->handle;
5705         uint32 buffer_size = q_u->buffer_size;
5706         uint8 *buffer = q_u->buffer;
5707         uint32 *buffer_written = &q_u->buffer_size2;
5708         int snum;
5709         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5710         
5711         if (!Printer) {
5712                 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5713                 r_u->buffer_written = q_u->buffer_size2;
5714                 return WERR_BADFID;
5715         }
5716
5717         if (!get_printer_snum(p, handle, &snum))
5718                 return WERR_BADFID;
5719
5720         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5721                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5722         if (*buffer_written == (uint32)-1) {
5723                 r_u->buffer_written = 0;
5724                 if (errno == ENOSPC)
5725                         return WERR_NO_SPOOL_SPACE;
5726                 else
5727                         return WERR_ACCESS_DENIED;
5728         }
5729
5730         r_u->buffer_written = q_u->buffer_size2;
5731
5732         return WERR_OK;
5733 }
5734
5735 /********************************************************************
5736  * api_spoolss_getprinter
5737  * called from the spoolss dispatcher
5738  *
5739  ********************************************************************/
5740
5741 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5742                               pipes_struct *p)
5743 {
5744         struct current_user user;
5745         int snum;
5746         WERROR errcode = WERR_BADFUNC;
5747         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5748
5749         get_current_user(&user, p);
5750
5751         if (!Printer) {
5752                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5753                 return WERR_BADFID;
5754         }
5755
5756         if (!get_printer_snum(p, handle, &snum))
5757                 return WERR_BADFID;
5758
5759         switch (command) {
5760         case PRINTER_CONTROL_PAUSE:
5761                 if (print_queue_pause(&user, snum, &errcode)) {
5762                         errcode = WERR_OK;
5763                 }
5764                 break;
5765         case PRINTER_CONTROL_RESUME:
5766         case PRINTER_CONTROL_UNPAUSE:
5767                 if (print_queue_resume(&user, snum, &errcode)) {
5768                         errcode = WERR_OK;
5769                 }
5770                 break;
5771         case PRINTER_CONTROL_PURGE:
5772                 if (print_queue_purge(&user, snum, &errcode)) {
5773                         errcode = WERR_OK;
5774                 }
5775                 break;
5776         default:
5777                 return WERR_UNKNOWN_LEVEL;
5778         }
5779
5780         return errcode;
5781 }
5782
5783 /********************************************************************
5784  * api_spoolss_abortprinter
5785  * From MSDN: "Deletes printer's spool file if printer is configured
5786  * for spooling"
5787  ********************************************************************/
5788
5789 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5790 {
5791         POLICY_HND      *handle = &q_u->handle;
5792         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5793         int             snum;
5794         struct          current_user user;
5795         WERROR          errcode = WERR_OK;
5796         
5797         if (!Printer) {
5798                 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5799                 return WERR_BADFID;
5800         }
5801         
5802         if (!get_printer_snum(p, handle, &snum))
5803                 return WERR_BADFID;
5804         
5805         get_current_user( &user, p );   
5806         
5807         print_job_delete( &user, snum, Printer->jobid, &errcode );      
5808         
5809         return errcode;
5810 }
5811
5812 /********************************************************************
5813  * called by spoolss_api_setprinter
5814  * when updating a printer description
5815  ********************************************************************/
5816
5817 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5818                                  const SPOOL_PRINTER_INFO_LEVEL *info,
5819                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5820 {
5821         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5822         WERROR result;
5823         int snum;
5824
5825         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5826
5827         if (!Printer || !get_printer_snum(p, handle, &snum)) {
5828                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5829                          OUR_HANDLE(handle)));
5830
5831                 result = WERR_BADFID;
5832                 goto done;
5833         }
5834         
5835         /* Check the user has permissions to change the security
5836            descriptor.  By experimentation with two NT machines, the user
5837            requires Full Access to the printer to change security
5838            information. */
5839
5840         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5841                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5842                 result = WERR_ACCESS_DENIED;
5843                 goto done;
5844         }
5845
5846         /* NT seems to like setting the security descriptor even though
5847            nothing may have actually changed. */
5848
5849         nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5850
5851         if (DEBUGLEVEL >= 10) {
5852                 SEC_ACL *the_acl;
5853                 int i;
5854
5855                 the_acl = old_secdesc_ctr->sec->dacl;
5856                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
5857                            PRINTERNAME(snum), the_acl->num_aces));
5858
5859                 for (i = 0; i < the_acl->num_aces; i++) {
5860                         fstring sid_str;
5861
5862                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5863
5864                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
5865                                   the_acl->ace[i].info.mask));
5866                 }
5867
5868                 the_acl = secdesc_ctr->sec->dacl;
5869
5870                 if (the_acl) {
5871                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5872                                    PRINTERNAME(snum), the_acl->num_aces));
5873
5874                         for (i = 0; i < the_acl->num_aces; i++) {
5875                                 fstring sid_str;
5876                                 
5877                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5878                                 
5879                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
5880                                            the_acl->ace[i].info.mask));
5881                         }
5882                 } else {
5883                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5884                 }
5885         }
5886
5887         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5888
5889         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5890                 result = WERR_OK;
5891                 goto done;
5892         }
5893
5894         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5895
5896  done:
5897
5898         return result;
5899 }
5900
5901 /********************************************************************
5902  Canonicalize printer info from a client
5903
5904  ATTN: It does not matter what we set the servername to hear 
5905  since we do the necessary work in get_a_printer() to set it to 
5906  the correct value based on what the client sent in the 
5907  _spoolss_open_printer_ex().
5908  ********************************************************************/
5909
5910 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5911 {
5912         fstring printername;
5913         const char *p;
5914         
5915         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5916                 "portname=%s drivername=%s comment=%s location=%s\n",
5917                 info->servername, info->printername, info->sharename, 
5918                 info->portname, info->drivername, info->comment, info->location));
5919
5920         /* we force some elements to "correct" values */
5921         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5922         fstrcpy(info->sharename, lp_servicename(snum));
5923         
5924         /* check to see if we allow printername != sharename */
5925
5926         if ( lp_force_printername(snum) ) {
5927                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5928                         global_myname(), info->sharename );
5929         } else {
5930
5931                 /* make sure printername is in \\server\printername format */
5932         
5933                 fstrcpy( printername, info->printername );
5934                 p = printername;
5935                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5936                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5937                                 p++;
5938                 }
5939                 
5940                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5941                          global_myname(), p );
5942         }
5943
5944         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5945         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5946         
5947         
5948         
5949         return True;
5950 }
5951
5952 /****************************************************************************
5953 ****************************************************************************/
5954
5955 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5956 {
5957         char *cmd = lp_addprinter_cmd();
5958         char **qlines;
5959         pstring command;
5960         int numlines;
5961         int ret;
5962         int fd;
5963         fstring remote_machine = "%m";
5964         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5965         BOOL is_print_op = False;
5966
5967         standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5968         
5969         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5970                         cmd, printer->info_2->printername, printer->info_2->sharename,
5971                         printer->info_2->portname, printer->info_2->drivername,
5972                         printer->info_2->location, printer->info_2->comment, remote_machine);
5973
5974         if ( token )
5975                 is_print_op = user_has_privileges( token, &se_printop );
5976
5977         DEBUG(10,("Running [%s]\n", command));
5978
5979         /********* BEGIN SePrintOperatorPrivilege **********/
5980
5981         if ( is_print_op )
5982                 become_root();
5983         
5984         if ( (ret = smbrun(command, &fd)) == 0 ) {
5985                 /* Tell everyone we updated smb.conf. */
5986                 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5987         }
5988
5989         if ( is_print_op )
5990                 unbecome_root();
5991
5992         /********* END SePrintOperatorPrivilege **********/
5993
5994         DEBUGADD(10,("returned [%d]\n", ret));
5995
5996         if ( ret != 0 ) {
5997                 if (fd != -1)
5998                         close(fd);
5999                 return False;
6000         }
6001
6002         /* reload our services immediately */
6003         reload_services( False );
6004
6005         numlines = 0;
6006         /* Get lines and convert them back to dos-codepage */
6007         qlines = fd_lines_load(fd, &numlines);
6008         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6009         close(fd);
6010
6011         /* Set the portname to what the script says the portname should be. */
6012         /* but don't require anything to be return from the script exit a good error code */
6013
6014         if (numlines) {
6015                 /* Set the portname to what the script says the portname should be. */
6016                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6017                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6018         }
6019
6020         file_lines_free(qlines);
6021         return True;
6022 }
6023
6024 /********************************************************************
6025  * Called by spoolss_api_setprinter
6026  * when updating a printer description.
6027  ********************************************************************/
6028
6029 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6030                            const SPOOL_PRINTER_INFO_LEVEL *info,
6031                            DEVICEMODE *devmode)
6032 {
6033         int snum;
6034         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6035         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6036         WERROR result;
6037         UNISTR2 buffer;
6038         fstring asc_buffer;
6039
6040         DEBUG(8,("update_printer\n"));
6041
6042         result = WERR_OK;
6043
6044         if (!Printer) {
6045                 result = WERR_BADFID;
6046                 goto done;
6047         }
6048
6049         if (!get_printer_snum(p, handle, &snum)) {
6050                 result = WERR_BADFID;
6051                 goto done;
6052         }
6053
6054         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6055             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6056                 result = WERR_BADFID;
6057                 goto done;
6058         }
6059
6060         DEBUGADD(8,("Converting info_2 struct\n"));
6061
6062         /*
6063          * convert_printer_info converts the incoming
6064          * info from the client and overwrites the info
6065          * just read from the tdb in the pointer 'printer'.
6066          */
6067
6068         if (!convert_printer_info(info, printer, level)) {
6069                 result =  WERR_NOMEM;
6070                 goto done;
6071         }
6072
6073         if (devmode) {
6074                 /* we have a valid devmode
6075                    convert it and link it*/
6076
6077                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6078                 if (!convert_devicemode(printer->info_2->printername, devmode,
6079                                 &printer->info_2->devmode)) {
6080                         result =  WERR_NOMEM;
6081                         goto done;
6082                 }
6083         }
6084
6085         /* Do sanity check on the requested changes for Samba */
6086
6087         if (!check_printer_ok(printer->info_2, snum)) {
6088                 result = WERR_INVALID_PARAM;
6089                 goto done;
6090         }
6091
6092         /* FIXME!!! If the driver has changed we really should verify that 
6093            it is installed before doing much else   --jerry */
6094
6095         /* Check calling user has permission to update printer description */
6096
6097         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6098                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6099                 result = WERR_ACCESS_DENIED;
6100                 goto done;
6101         }
6102
6103         /* Call addprinter hook */
6104         /* Check changes to see if this is really needed */
6105         
6106         if ( *lp_addprinter_cmd() 
6107                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6108                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6109                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6110                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6111         {
6112                 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6113                         result = WERR_ACCESS_DENIED;
6114                         goto done;
6115                 }
6116
6117                 /* 
6118                  * make sure we actually reload the services after 
6119                  * this as smb.conf could have a new section in it 
6120                  * .... shouldn't .... but could
6121                  */
6122                 reload_services(False); 
6123         }
6124         
6125         /*
6126          * When a *new* driver is bound to a printer, the drivername is used to
6127          * lookup previously saved driver initialization info, which is then
6128          * bound to the printer, simulating what happens in the Windows arch.
6129          */
6130         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6131         {
6132                 if (!set_driver_init(printer, 2)) 
6133                 {
6134                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6135                                 printer->info_2->drivername));
6136                 }
6137                 
6138                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6139                         printer->info_2->drivername));
6140                         
6141                 notify_printer_driver(snum, printer->info_2->drivername);
6142         }
6143
6144         /* 
6145          * flag which changes actually occured.  This is a small subset of 
6146          * all the possible changes.  We also have to update things in the 
6147          * DsSpooler key.
6148          */
6149
6150         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6151                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6152                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6153                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6154
6155                 notify_printer_comment(snum, printer->info_2->comment);
6156         }
6157
6158         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6159                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6160                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6161                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6162
6163                 notify_printer_sharename(snum, printer->info_2->sharename);
6164         }
6165
6166         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6167                 char *pname;
6168                 
6169                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6170                         pname++;
6171                 else
6172                         pname = printer->info_2->printername;
6173                         
6174
6175                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6176                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6177                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6178
6179                 notify_printer_printername( snum, pname );
6180         }
6181         
6182         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6183                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6184                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6185                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6186
6187                 notify_printer_port(snum, printer->info_2->portname);
6188         }
6189
6190         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6191                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6192                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6193                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6194
6195                 notify_printer_location(snum, printer->info_2->location);
6196         }
6197         
6198         /* here we need to update some more DsSpooler keys */
6199         /* uNCName, serverName, shortServerName */
6200         
6201         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6202         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6203                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6204         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6205                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6206
6207         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6208                  global_myname(), printer->info_2->sharename );
6209         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6210         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6211                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6212
6213         /* Update printer info */
6214         result = mod_a_printer(printer, 2);
6215
6216 done:
6217         free_a_printer(&printer, 2);
6218         free_a_printer(&old_printer, 2);
6219
6220
6221         return result;
6222 }
6223
6224 /****************************************************************************
6225 ****************************************************************************/
6226 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6227                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6228 {
6229 #ifdef HAVE_ADS
6230         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6231         int snum;
6232         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6233
6234         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6235
6236         if (!Printer)
6237                 return WERR_BADFID;
6238
6239         if (!get_printer_snum(p, handle, &snum))
6240                 return WERR_BADFID;
6241         
6242         nt_printer_publish(Printer, snum, info7->action);
6243         
6244         return WERR_OK;
6245 #else
6246         return WERR_UNKNOWN_LEVEL;
6247 #endif
6248 }
6249 /****************************************************************************
6250 ****************************************************************************/
6251
6252 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6253 {
6254         POLICY_HND *handle = &q_u->handle;
6255         uint32 level = q_u->level;
6256         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6257         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6258         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6259         uint32 command = q_u->command;
6260         WERROR result;
6261
6262         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6263         
6264         if (!Printer) {
6265                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6266                 return WERR_BADFID;
6267         }
6268
6269         /* check the level */   
6270         switch (level) {
6271                 case 0:
6272                         return control_printer(handle, command, p);
6273                 case 2:
6274                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6275                         if (!W_ERROR_IS_OK(result)) 
6276                                 return result;
6277                         if (secdesc_ctr)
6278                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6279                         return result;
6280                 case 3:
6281                         return update_printer_sec(handle, level, info, p,
6282                                                   secdesc_ctr);
6283                 case 7:
6284                         return publish_or_unpublish_printer(p, handle, info);
6285                 default:
6286                         return WERR_UNKNOWN_LEVEL;
6287         }
6288 }
6289
6290 /****************************************************************************
6291 ****************************************************************************/
6292
6293 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6294 {
6295         POLICY_HND *handle = &q_u->handle;
6296         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6297         
6298         if (!Printer) {
6299                 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6300                 return WERR_BADFID;
6301         }
6302
6303         if (Printer->notify.client_connected==True) {
6304                 int snum = -1;
6305
6306                 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6307                         snum = -1;
6308                 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6309                                 !get_printer_snum(p, handle, &snum) )
6310                         return WERR_BADFID;
6311
6312                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6313         }
6314
6315         Printer->notify.flags=0;
6316         Printer->notify.options=0;
6317         Printer->notify.localmachine[0]='\0';
6318         Printer->notify.printerlocal=0;
6319         if (Printer->notify.option)
6320                 free_spool_notify_option(&Printer->notify.option);
6321         Printer->notify.client_connected=False;
6322
6323         return WERR_OK;
6324 }
6325
6326 /****************************************************************************
6327 ****************************************************************************/
6328
6329 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6330 {
6331         /* that's an [in out] buffer */
6332
6333         if ( q_u->buffer ) 
6334                 rpcbuf_move(q_u->buffer, &r_u->buffer);
6335
6336         r_u->needed = 0;
6337         return WERR_INVALID_PARAM; /* this is what a NT server
6338                                            returns for AddJob. AddJob
6339                                            must fail on non-local
6340                                            printers */
6341 }
6342
6343 /****************************************************************************
6344 ****************************************************************************/
6345
6346 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6347                             int position, int snum, 
6348                             NT_PRINTER_INFO_LEVEL *ntprinter)
6349 {
6350         struct tm *t;
6351         
6352         t=gmtime(&queue->time);
6353
6354         job_info->jobid=queue->job;     
6355         init_unistr(&job_info->printername, lp_servicename(snum));
6356         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6357         init_unistr(&job_info->username, queue->fs_user);
6358         init_unistr(&job_info->document, queue->fs_file);
6359         init_unistr(&job_info->datatype, "RAW");
6360         init_unistr(&job_info->text_status, "");
6361         job_info->status=nt_printj_status(queue->status);
6362         job_info->priority=queue->priority;
6363         job_info->position=position;
6364         job_info->totalpages=queue->page_count;
6365         job_info->pagesprinted=0;
6366
6367         make_systemtime(&job_info->submitted, t);
6368 }
6369
6370 /****************************************************************************
6371 ****************************************************************************/
6372
6373 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6374                             int position, int snum, 
6375                             NT_PRINTER_INFO_LEVEL *ntprinter,
6376                             DEVICEMODE *devmode)
6377 {
6378         struct tm *t;
6379
6380         t=gmtime(&queue->time);
6381
6382         job_info->jobid=queue->job;
6383         
6384         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6385         
6386         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6387         init_unistr(&job_info->username, queue->fs_user);
6388         init_unistr(&job_info->document, queue->fs_file);
6389         init_unistr(&job_info->notifyname, queue->fs_user);
6390         init_unistr(&job_info->datatype, "RAW");
6391         init_unistr(&job_info->printprocessor, "winprint");
6392         init_unistr(&job_info->parameters, "");
6393         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6394         init_unistr(&job_info->text_status, "");
6395         
6396 /* and here the security descriptor */
6397
6398         job_info->status=nt_printj_status(queue->status);
6399         job_info->priority=queue->priority;
6400         job_info->position=position;
6401         job_info->starttime=0;
6402         job_info->untiltime=0;
6403         job_info->totalpages=queue->page_count;
6404         job_info->size=queue->size;
6405         make_systemtime(&(job_info->submitted), t);
6406         job_info->timeelapsed=0;
6407         job_info->pagesprinted=0;
6408
6409         job_info->devmode = devmode;
6410
6411         return (True);
6412 }
6413
6414 /****************************************************************************
6415  Enumjobs at level 1.
6416 ****************************************************************************/
6417
6418 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6419                               NT_PRINTER_INFO_LEVEL *ntprinter,
6420                               RPC_BUFFER *buffer, uint32 offered,
6421                               uint32 *needed, uint32 *returned)
6422 {
6423         JOB_INFO_1 *info;
6424         int i;
6425         WERROR result = WERR_OK;
6426         
6427         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6428         if (info==NULL) {
6429                 SAFE_FREE(queue);
6430                 *returned=0;
6431                 return WERR_NOMEM;
6432         }
6433         
6434         for (i=0; i<*returned; i++)
6435                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6436
6437         SAFE_FREE(queue);
6438
6439         /* check the required size. */  
6440         for (i=0; i<*returned; i++)
6441                 (*needed) += spoolss_size_job_info_1(&info[i]);
6442
6443         if (*needed > offered) {
6444                 result = WERR_INSUFFICIENT_BUFFER;
6445                 goto out;
6446         }
6447
6448         if (!rpcbuf_alloc_size(buffer, *needed)) {
6449                 result = WERR_NOMEM;
6450                 goto out;
6451         }
6452
6453         /* fill the buffer with the structures */
6454         for (i=0; i<*returned; i++)
6455                 smb_io_job_info_1("", buffer, &info[i], 0);     
6456
6457 out:
6458         /* clear memory */
6459         SAFE_FREE(info);
6460
6461         if ( !W_ERROR_IS_OK(result) )
6462                 *returned = 0;
6463
6464         return result;
6465 }
6466
6467 /****************************************************************************
6468  Enumjobs at level 2.
6469 ****************************************************************************/
6470
6471 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6472                               NT_PRINTER_INFO_LEVEL *ntprinter,
6473                               RPC_BUFFER *buffer, uint32 offered,
6474                               uint32 *needed, uint32 *returned)
6475 {
6476         JOB_INFO_2 *info = NULL;
6477         int i;
6478         WERROR result = WERR_OK;
6479         DEVICEMODE *devmode = NULL;
6480         
6481         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6482                 *returned=0;
6483                 return WERR_NOMEM;
6484         }
6485                 
6486         /* this should not be a failure condition if the devmode is NULL */
6487         
6488         devmode = construct_dev_mode(snum);
6489
6490         for (i=0; i<*returned; i++)
6491                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6492
6493         free_a_printer(&ntprinter, 2);
6494         SAFE_FREE(queue);
6495
6496         /* check the required size. */  
6497         for (i=0; i<*returned; i++)
6498                 (*needed) += spoolss_size_job_info_2(&info[i]);
6499
6500         if (*needed > offered) {
6501                 result = WERR_INSUFFICIENT_BUFFER;
6502                 goto out;
6503         }
6504
6505         if (!rpcbuf_alloc_size(buffer, *needed)) {
6506                 result = WERR_NOMEM;
6507                 goto out;
6508         }
6509
6510         /* fill the buffer with the structures */
6511         for (i=0; i<*returned; i++)
6512                 smb_io_job_info_2("", buffer, &info[i], 0);     
6513
6514 out:
6515         free_devmode(devmode);
6516         SAFE_FREE(info);
6517
6518         if ( !W_ERROR_IS_OK(result) )
6519                 *returned = 0;
6520
6521         return result;
6522
6523 }
6524
6525 /****************************************************************************
6526  Enumjobs.
6527 ****************************************************************************/
6528
6529 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6530 {       
6531         POLICY_HND *handle = &q_u->handle;
6532         uint32 level = q_u->level;
6533         RPC_BUFFER *buffer = NULL;
6534         uint32 offered = q_u->offered;
6535         uint32 *needed = &r_u->needed;
6536         uint32 *returned = &r_u->returned;
6537         WERROR wret;
6538         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6539         int snum;
6540         print_status_struct prt_status;
6541         print_queue_struct *queue=NULL;
6542
6543         /* that's an [in out] buffer */
6544
6545         if ( q_u->buffer ) {
6546                 rpcbuf_move(q_u->buffer, &r_u->buffer);
6547                 buffer = r_u->buffer;
6548         }
6549
6550         DEBUG(4,("_spoolss_enumjobs\n"));
6551
6552         *needed=0;
6553         *returned=0;
6554
6555         /* lookup the printer snum and tdb entry */
6556         
6557         if (!get_printer_snum(p, handle, &snum))
6558                 return WERR_BADFID;
6559
6560         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6561         if ( !W_ERROR_IS_OK(wret) )
6562                 return wret;
6563         
6564         *returned = print_queue_status(snum, &queue, &prt_status);
6565         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6566
6567         if (*returned == 0) {
6568                 SAFE_FREE(queue);
6569                 return WERR_OK;
6570         }
6571
6572         switch (level) {
6573         case 1:
6574                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6575                 return wret;
6576         case 2:
6577                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6578                 return wret;
6579         default:
6580                 SAFE_FREE(queue);
6581                 *returned=0;
6582                 wret = WERR_UNKNOWN_LEVEL;
6583         }
6584         
6585         free_a_printer( &ntprinter, 2 );
6586         return wret;
6587 }
6588
6589 /****************************************************************************
6590 ****************************************************************************/
6591
6592 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6593 {
6594         return WERR_OK;
6595 }
6596
6597 /****************************************************************************
6598 ****************************************************************************/
6599
6600 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6601 {
6602         POLICY_HND *handle = &q_u->handle;
6603         uint32 jobid = q_u->jobid;
6604         uint32 command = q_u->command;
6605
6606         struct current_user user;
6607         int snum;
6608         WERROR errcode = WERR_BADFUNC;
6609                 
6610         if (!get_printer_snum(p, handle, &snum)) {
6611                 return WERR_BADFID;
6612         }
6613
6614         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6615                 return WERR_INVALID_PRINTER_NAME;
6616         }
6617
6618         get_current_user(&user, p);     
6619
6620         switch (command) {
6621         case JOB_CONTROL_CANCEL:
6622         case JOB_CONTROL_DELETE:
6623                 if (print_job_delete(&user, snum, jobid, &errcode)) {
6624                         errcode = WERR_OK;
6625                 }
6626                 break;
6627         case JOB_CONTROL_PAUSE:
6628                 if (print_job_pause(&user, snum, jobid, &errcode)) {
6629                         errcode = WERR_OK;
6630                 }               
6631                 break;
6632         case JOB_CONTROL_RESTART:
6633         case JOB_CONTROL_RESUME:
6634                 if (print_job_resume(&user, snum, jobid, &errcode)) {
6635                         errcode = WERR_OK;
6636                 }
6637                 break;
6638         default:
6639                 return WERR_UNKNOWN_LEVEL;
6640         }
6641
6642         return errcode;
6643 }
6644
6645 /****************************************************************************
6646  Enumerates all printer drivers at level 1.
6647 ****************************************************************************/
6648
6649 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6650 {
6651         int i;
6652         int ndrivers;
6653         uint32 version;
6654         fstring *list = NULL;
6655         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6656         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6657         WERROR result = WERR_OK;
6658
6659         *returned=0;
6660
6661         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6662                 list=NULL;
6663                 ndrivers=get_ntdrivers(&list, architecture, version);
6664                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6665
6666                 if(ndrivers == -1)
6667                         return WERR_NOMEM;
6668
6669                 if(ndrivers != 0) {
6670                         if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6671                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6672                                 SAFE_FREE(driver_info_1);
6673                                 SAFE_FREE(list);
6674                                 return WERR_NOMEM;
6675                         }
6676                         else driver_info_1 = tdi1;
6677                 }
6678
6679                 for (i=0; i<ndrivers; i++) {
6680                         WERROR status;
6681                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6682                         ZERO_STRUCT(driver);
6683                         status = get_a_printer_driver(&driver, 3, list[i], 
6684                                                       architecture, version);
6685                         if (!W_ERROR_IS_OK(status)) {
6686                                 SAFE_FREE(list);
6687                                 return status;
6688                         }
6689                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
6690                         free_a_printer_driver(driver, 3);
6691                 }       
6692
6693                 *returned+=ndrivers;
6694                 SAFE_FREE(list);
6695         }
6696         
6697         /* check the required size. */
6698         for (i=0; i<*returned; i++) {
6699                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6700                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6701         }
6702
6703         if (*needed > offered) {
6704                 result = WERR_INSUFFICIENT_BUFFER;
6705                 goto out;
6706         }
6707
6708         if (!rpcbuf_alloc_size(buffer, *needed)) {
6709                 result = WERR_NOMEM;    
6710                 goto out;
6711         }
6712
6713         /* fill the buffer with the driver structures */
6714         for (i=0; i<*returned; i++) {
6715                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6716                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6717         }
6718
6719 out:
6720         SAFE_FREE(driver_info_1);
6721
6722         if ( !W_ERROR_IS_OK(result) )
6723                 *returned = 0;
6724
6725         return result;
6726 }
6727
6728 /****************************************************************************
6729  Enumerates all printer drivers at level 2.
6730 ****************************************************************************/
6731
6732 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6733 {
6734         int i;
6735         int ndrivers;
6736         uint32 version;
6737         fstring *list = NULL;
6738         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6739         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6740         WERROR result = WERR_OK;
6741
6742         *returned=0;
6743
6744         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6745                 list=NULL;
6746                 ndrivers=get_ntdrivers(&list, architecture, version);
6747                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6748
6749                 if(ndrivers == -1)
6750                         return WERR_NOMEM;
6751
6752                 if(ndrivers != 0) {
6753                         if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6754                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6755                                 SAFE_FREE(driver_info_2);
6756                                 SAFE_FREE(list);
6757                                 return WERR_NOMEM;
6758                         }
6759                         else driver_info_2 = tdi2;
6760                 }
6761                 
6762                 for (i=0; i<ndrivers; i++) {
6763                         WERROR status;
6764
6765                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6766                         ZERO_STRUCT(driver);
6767                         status = get_a_printer_driver(&driver, 3, list[i], 
6768                                                       architecture, version);
6769                         if (!W_ERROR_IS_OK(status)) {
6770                                 SAFE_FREE(list);
6771                                 return status;
6772                         }
6773                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
6774                         free_a_printer_driver(driver, 3);
6775                 }       
6776
6777                 *returned+=ndrivers;
6778                 SAFE_FREE(list);
6779         }
6780         
6781         /* check the required size. */
6782         for (i=0; i<*returned; i++) {
6783                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6784                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6785         }
6786
6787         if (*needed > offered) {
6788                 result = WERR_INSUFFICIENT_BUFFER;
6789                 goto out;
6790         }
6791
6792         if (!rpcbuf_alloc_size(buffer, *needed)) {
6793                 result = WERR_NOMEM;    
6794                 goto out;
6795         }
6796
6797         /* fill the buffer with the form structures */
6798         for (i=0; i<*returned; i++) {
6799                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6800                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6801         }
6802
6803 out:
6804         SAFE_FREE(driver_info_2);
6805
6806         if ( !W_ERROR_IS_OK(result) )
6807                 *returned = 0;
6808
6809         return result;
6810 }
6811
6812 /****************************************************************************
6813  Enumerates all printer drivers at level 3.
6814 ****************************************************************************/
6815
6816 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6817 {
6818         int i;
6819         int ndrivers;
6820         uint32 version;
6821         fstring *list = NULL;
6822         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6823         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6824         WERROR result = WERR_OK;
6825
6826         *returned=0;
6827
6828         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6829                 list=NULL;
6830                 ndrivers=get_ntdrivers(&list, architecture, version);
6831                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6832
6833                 if(ndrivers == -1)
6834                         return WERR_NOMEM;
6835
6836                 if(ndrivers != 0) {
6837                         if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6838                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6839                                 SAFE_FREE(driver_info_3);
6840                                 SAFE_FREE(list);
6841                                 return WERR_NOMEM;
6842                         }
6843                         else driver_info_3 = tdi3;
6844                 }
6845
6846                 for (i=0; i<ndrivers; i++) {
6847                         WERROR status;
6848
6849                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6850                         ZERO_STRUCT(driver);
6851                         status = get_a_printer_driver(&driver, 3, list[i], 
6852                                                       architecture, version);
6853                         if (!W_ERROR_IS_OK(status)) {
6854                                 SAFE_FREE(list);
6855                                 return status;
6856                         }
6857                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
6858                         free_a_printer_driver(driver, 3);
6859                 }       
6860
6861                 *returned+=ndrivers;
6862                 SAFE_FREE(list);
6863         }
6864
6865         /* check the required size. */
6866         for (i=0; i<*returned; i++) {
6867                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6868                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6869         }
6870
6871         if (*needed > offered) {
6872                 result = WERR_INSUFFICIENT_BUFFER;
6873                 goto out;
6874         }
6875
6876         if (!rpcbuf_alloc_size(buffer, *needed)) {
6877                 result = WERR_NOMEM;    
6878                 goto out;
6879         }
6880
6881         /* fill the buffer with the driver structures */
6882         for (i=0; i<*returned; i++) {
6883                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6884                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6885         }
6886
6887 out:
6888         for (i=0; i<*returned; i++)
6889                 SAFE_FREE(driver_info_3[i].dependentfiles);
6890
6891         SAFE_FREE(driver_info_3);
6892         
6893         if ( !W_ERROR_IS_OK(result) )
6894                 *returned = 0;
6895
6896         return result;
6897 }
6898
6899 /****************************************************************************
6900  Enumerates all printer drivers.
6901 ****************************************************************************/
6902
6903 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6904 {
6905         uint32 level = q_u->level;
6906         RPC_BUFFER *buffer = NULL;
6907         uint32 offered = q_u->offered;
6908         uint32 *needed = &r_u->needed;
6909         uint32 *returned = &r_u->returned;
6910
6911         fstring servername;
6912         fstring architecture;
6913
6914         /* that's an [in out] buffer */
6915
6916         if ( q_u->buffer ) {
6917                 rpcbuf_move(q_u->buffer, &r_u->buffer);
6918                 buffer = r_u->buffer;
6919         }
6920
6921         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6922         
6923         *needed   = 0;
6924         *returned = 0;
6925
6926         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6927         unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6928
6929         if ( !is_myname_or_ipaddr( servername ) )
6930                 return WERR_UNKNOWN_PRINTER_DRIVER;
6931
6932         switch (level) {
6933         case 1:
6934                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6935         case 2:
6936                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6937         case 3:
6938                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6939         default:
6940                 return WERR_UNKNOWN_LEVEL;
6941         }
6942 }
6943
6944 /****************************************************************************
6945 ****************************************************************************/
6946
6947 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6948 {
6949         form->flag=list->flag;
6950         init_unistr(&form->name, list->name);
6951         form->width=list->width;
6952         form->length=list->length;
6953         form->left=list->left;
6954         form->top=list->top;
6955         form->right=list->right;
6956         form->bottom=list->bottom;      
6957 }
6958         
6959 /****************************************************************************
6960 ****************************************************************************/
6961
6962 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6963 {
6964         uint32 level = q_u->level;
6965         RPC_BUFFER *buffer = NULL;
6966         uint32 offered = q_u->offered;
6967         uint32 *needed = &r_u->needed;
6968         uint32 *numofforms = &r_u->numofforms;
6969         uint32 numbuiltinforms;
6970
6971         nt_forms_struct *list=NULL;
6972         nt_forms_struct *builtinlist=NULL;
6973         FORM_1 *forms_1;
6974         int buffer_size=0;
6975         int i;
6976
6977         /* that's an [in out] buffer */
6978
6979         if ( q_u->buffer ) {
6980                 rpcbuf_move(q_u->buffer, &r_u->buffer);
6981                 buffer = r_u->buffer;
6982         }
6983
6984         DEBUG(4,("_spoolss_enumforms\n"));
6985         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6986         DEBUGADD(5,("Info level [%d]\n",          level));
6987
6988         numbuiltinforms = get_builtin_ntforms(&builtinlist);
6989         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
6990         *numofforms = get_ntforms(&list);
6991         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
6992         *numofforms += numbuiltinforms;
6993
6994         if (*numofforms == 0) 
6995                 return WERR_NO_MORE_ITEMS;
6996
6997         switch (level) {
6998         case 1:
6999                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7000                         *numofforms=0;
7001                         return WERR_NOMEM;
7002                 }
7003
7004                 /* construct the list of form structures */
7005                 for (i=0; i<numbuiltinforms; i++) {
7006                         DEBUGADD(6,("Filling form number [%d]\n",i));
7007                         fill_form_1(&forms_1[i], &builtinlist[i]);
7008                 }
7009                 
7010                 SAFE_FREE(builtinlist);
7011
7012                 for (; i<*numofforms; i++) {
7013                         DEBUGADD(6,("Filling form number [%d]\n",i));
7014                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7015                 }
7016                 
7017                 SAFE_FREE(list);
7018
7019                 /* check the required size. */
7020                 for (i=0; i<numbuiltinforms; i++) {
7021                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7022                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7023                 }
7024                 for (; i<*numofforms; i++) {
7025                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7026                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7027                 }
7028
7029                 *needed=buffer_size;            
7030                 
7031                 if (*needed > offered) {
7032                         SAFE_FREE(forms_1);
7033                         *numofforms=0;
7034                         return WERR_INSUFFICIENT_BUFFER;
7035                 }
7036         
7037                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7038                         SAFE_FREE(forms_1);
7039                         *numofforms=0;
7040                         return WERR_NOMEM;
7041                 }
7042
7043                 /* fill the buffer with the form structures */
7044                 for (i=0; i<numbuiltinforms; i++) {
7045                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7046                         smb_io_form_1("", buffer, &forms_1[i], 0);
7047                 }
7048                 for (; i<*numofforms; i++) {
7049                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7050                         smb_io_form_1("", buffer, &forms_1[i], 0);
7051                 }
7052
7053                 SAFE_FREE(forms_1);
7054
7055                 return WERR_OK;
7056                         
7057         default:
7058                 SAFE_FREE(list);
7059                 SAFE_FREE(builtinlist);
7060                 return WERR_UNKNOWN_LEVEL;
7061         }
7062
7063 }
7064
7065 /****************************************************************************
7066 ****************************************************************************/
7067
7068 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7069 {
7070         uint32 level = q_u->level;
7071         UNISTR2 *uni_formname = &q_u->formname;
7072         RPC_BUFFER *buffer = NULL;
7073         uint32 offered = q_u->offered;
7074         uint32 *needed = &r_u->needed;
7075
7076         nt_forms_struct *list=NULL;
7077         nt_forms_struct builtin_form;
7078         BOOL foundBuiltin;
7079         FORM_1 form_1;
7080         fstring form_name;
7081         int buffer_size=0;
7082         int numofforms=0, i=0;
7083
7084         /* that's an [in out] buffer */
7085
7086         if ( q_u->buffer ) {
7087                 rpcbuf_move(q_u->buffer, &r_u->buffer);
7088                 buffer = r_u->buffer;
7089         }
7090
7091         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7092
7093         DEBUG(4,("_spoolss_getform\n"));
7094         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7095         DEBUGADD(5,("Info level [%d]\n",          level));
7096
7097         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7098         if (!foundBuiltin) {
7099                 numofforms = get_ntforms(&list);
7100                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7101
7102                 if (numofforms == 0)
7103                         return WERR_BADFID;
7104         }
7105
7106         switch (level) {
7107         case 1:
7108                 if (foundBuiltin) {
7109                         fill_form_1(&form_1, &builtin_form);
7110                 } else {
7111
7112                         /* Check if the requested name is in the list of form structures */
7113                         for (i=0; i<numofforms; i++) {
7114
7115                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7116
7117                                 if (strequal(form_name, list[i].name)) {
7118                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7119                                         fill_form_1(&form_1, &list[i]);
7120                                         break;
7121                                 }
7122                         }
7123                         
7124                         SAFE_FREE(list);
7125                         if (i == numofforms) {
7126                                 return WERR_BADFID;
7127                         }
7128                 }
7129                 /* check the required size. */
7130
7131                 *needed=spoolss_size_form_1(&form_1);
7132                 
7133                 if (*needed > offered) 
7134                         return WERR_INSUFFICIENT_BUFFER;
7135
7136                 if (!rpcbuf_alloc_size(buffer, buffer_size))
7137                         return WERR_NOMEM;
7138
7139                 /* fill the buffer with the form structures */
7140                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7141                 smb_io_form_1("", buffer, &form_1, 0);
7142
7143                 return WERR_OK;
7144                         
7145         default:
7146                 SAFE_FREE(list);
7147                 return WERR_UNKNOWN_LEVEL;
7148         }
7149 }
7150
7151 /****************************************************************************
7152 ****************************************************************************/
7153
7154 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7155 {
7156         init_unistr(&port->port_name, name);
7157 }
7158
7159 /****************************************************************************
7160 ****************************************************************************/
7161
7162 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7163 {
7164         init_unistr(&port->port_name, name);
7165         init_unistr(&port->monitor_name, "Local Monitor");
7166         init_unistr(&port->description, "Local Port");
7167         port->port_type=PORT_TYPE_WRITE;
7168         port->reserved=0x0;     
7169 }
7170
7171
7172 /****************************************************************************
7173  wrapper around the enumer ports command
7174 ****************************************************************************/
7175
7176 WERROR enumports_hook( int *count, char ***lines )
7177 {
7178         char *cmd = lp_enumports_cmd();
7179         char **qlines;
7180         pstring command;
7181         int numlines;
7182         int ret;
7183         int fd;
7184
7185
7186         /* if no hook then just fill in the default port */
7187         
7188         if ( !*cmd ) {
7189                 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7190                 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7191                 qlines[1] = NULL;
7192                 numlines = 1;
7193         }
7194         else {
7195                 /* we have a valid enumport command */
7196                 
7197                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7198
7199                 DEBUG(10,("Running [%s]\n", command));
7200                 ret = smbrun(command, &fd);
7201                 DEBUG(10,("Returned [%d]\n", ret));
7202                 if (ret != 0) {
7203                         if (fd != -1)
7204                                 close(fd);
7205                         
7206                         return WERR_ACCESS_DENIED;
7207                 }
7208
7209                 numlines = 0;
7210                 qlines = fd_lines_load(fd, &numlines);
7211                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7212                 close(fd);
7213         }
7214         
7215         *count = numlines;
7216         *lines = qlines;
7217
7218         return WERR_OK;
7219 }
7220
7221 /****************************************************************************
7222  enumports level 1.
7223 ****************************************************************************/
7224
7225 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7226 {
7227         PORT_INFO_1 *ports=NULL;
7228         int i=0;
7229         WERROR result = WERR_OK;
7230         char **qlines;
7231         int numlines;
7232
7233         if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) ) 
7234                 return result;
7235         
7236         if(numlines) {
7237                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7238                         DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
7239                                   dos_errstr(WERR_NOMEM)));
7240                         file_lines_free(qlines);
7241                         return WERR_NOMEM;
7242                 }
7243
7244                 for (i=0; i<numlines; i++) {
7245                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7246                         fill_port_1(&ports[i], qlines[i]);
7247                 }
7248
7249                 file_lines_free(qlines);
7250         }
7251
7252         *returned = numlines;
7253
7254         /* check the required size. */
7255         for (i=0; i<*returned; i++) {
7256                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7257                 *needed += spoolss_size_port_info_1(&ports[i]);
7258         }
7259                 
7260         if (*needed > offered) {
7261                 result = WERR_INSUFFICIENT_BUFFER;
7262                 goto out;
7263         }
7264
7265         if (!rpcbuf_alloc_size(buffer, *needed)) {
7266                 result = WERR_NOMEM;
7267                 goto out;
7268         }
7269
7270         /* fill the buffer with the ports structures */
7271         for (i=0; i<*returned; i++) {
7272                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7273                 smb_io_port_1("", buffer, &ports[i], 0);
7274         }
7275
7276 out:
7277         SAFE_FREE(ports);
7278
7279         if ( !W_ERROR_IS_OK(result) )
7280                 *returned = 0;
7281
7282         return result;
7283 }
7284
7285 /****************************************************************************
7286  enumports level 2.
7287 ****************************************************************************/
7288
7289 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7290 {
7291         PORT_INFO_2 *ports=NULL;
7292         int i=0;
7293         WERROR result = WERR_OK;
7294         char **qlines;
7295         int numlines;
7296
7297         if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) ) 
7298                 return result;
7299         
7300         
7301         if(numlines) {
7302                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7303                         file_lines_free(qlines);
7304                         return WERR_NOMEM;
7305                 }
7306
7307                 for (i=0; i<numlines; i++) {
7308                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7309                         fill_port_2(&(ports[i]), qlines[i]);
7310                 }
7311
7312                 file_lines_free(qlines);
7313         }
7314
7315         *returned = numlines;
7316
7317         /* check the required size. */
7318         for (i=0; i<*returned; i++) {
7319                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7320                 *needed += spoolss_size_port_info_2(&ports[i]);
7321         }
7322                 
7323         if (*needed > offered) {
7324                 result = WERR_INSUFFICIENT_BUFFER;
7325                 goto out;
7326         }
7327
7328         if (!rpcbuf_alloc_size(buffer, *needed)) {
7329                 result = WERR_NOMEM;
7330                 goto out;
7331         }
7332
7333         /* fill the buffer with the ports structures */
7334         for (i=0; i<*returned; i++) {
7335                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7336                 smb_io_port_2("", buffer, &ports[i], 0);
7337         }
7338
7339 out:
7340         SAFE_FREE(ports);
7341
7342         if ( !W_ERROR_IS_OK(result) )
7343                 *returned = 0;
7344
7345         return result;
7346 }
7347
7348 /****************************************************************************
7349  enumports.
7350 ****************************************************************************/
7351
7352 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7353 {
7354         uint32 level = q_u->level;
7355         RPC_BUFFER *buffer = NULL;
7356         uint32 offered = q_u->offered;
7357         uint32 *needed = &r_u->needed;
7358         uint32 *returned = &r_u->returned;
7359
7360         /* that's an [in out] buffer */
7361
7362         if ( q_u->buffer ) {
7363                 rpcbuf_move(q_u->buffer, &r_u->buffer);
7364                 buffer = r_u->buffer;
7365         }
7366
7367         DEBUG(4,("_spoolss_enumports\n"));
7368         
7369         *returned=0;
7370         *needed=0;
7371         
7372         switch (level) {
7373         case 1:
7374                 return enumports_level_1(buffer, offered, needed, returned);
7375         case 2:
7376                 return enumports_level_2(buffer, offered, needed, returned);
7377         default:
7378                 return WERR_UNKNOWN_LEVEL;
7379         }
7380 }
7381
7382 /****************************************************************************
7383 ****************************************************************************/
7384
7385 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7386                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7387                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7388                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7389                                 POLICY_HND *handle)
7390 {
7391         NT_PRINTER_INFO_LEVEL *printer = NULL;
7392         fstring name;
7393         int     snum;
7394         WERROR err = WERR_OK;
7395
7396         if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7397                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7398                 return WERR_NOMEM;
7399         }
7400
7401         ZERO_STRUCTP(printer);
7402
7403         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7404         if (!convert_printer_info(info, printer, 2)) {
7405                 free_a_printer(&printer, 2);
7406                 return WERR_NOMEM;
7407         }
7408
7409         /* check to see if the printer already exists */
7410
7411         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7412                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n", 
7413                         printer->info_2->sharename));
7414                 free_a_printer(&printer, 2);
7415                 return WERR_PRINTER_ALREADY_EXISTS;
7416         }
7417         
7418         /* FIXME!!!  smbd should check to see if the driver is installed before
7419            trying to add a printer like this  --jerry */
7420
7421         if (*lp_addprinter_cmd() ) {
7422                 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7423                         free_a_printer(&printer,2);
7424                         return WERR_ACCESS_DENIED;
7425                 }
7426         } else {
7427                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7428                         "smb.conf parameter \"addprinter command\" is defined. This"
7429                         "parameter must exist for this call to succeed\n",
7430                         printer->info_2->sharename ));
7431         }
7432
7433         /* use our primary netbios name since get_a_printer() will convert 
7434            it to what the client expects on a case by case basis */
7435
7436         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7437              printer->info_2->sharename);
7438
7439         
7440         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7441                 free_a_printer(&printer,2);
7442                 return WERR_ACCESS_DENIED;
7443         }
7444
7445         /* you must be a printer admin to add a new printer */
7446         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7447                 free_a_printer(&printer,2);
7448                 return WERR_ACCESS_DENIED;              
7449         }
7450         
7451         /*
7452          * Do sanity check on the requested changes for Samba.
7453          */
7454
7455         if (!check_printer_ok(printer->info_2, snum)) {
7456                 free_a_printer(&printer,2);
7457                 return WERR_INVALID_PARAM;
7458         }
7459
7460         /*
7461          * When a printer is created, the drivername bound to the printer is used
7462          * to lookup previously saved driver initialization info, which is then 
7463          * bound to the new printer, simulating what happens in the Windows arch.
7464          */
7465
7466         if (!devmode)
7467         {
7468                 set_driver_init(printer, 2);
7469         }
7470         else 
7471         {
7472                 /* A valid devmode was included, convert and link it
7473                 */
7474                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7475
7476                 if (!convert_devicemode(printer->info_2->printername, devmode,
7477                                 &printer->info_2->devmode))
7478                         return  WERR_NOMEM;
7479         }
7480
7481         /* write the ASCII on disk */
7482         err = mod_a_printer(printer, 2);
7483         if (!W_ERROR_IS_OK(err)) {
7484                 free_a_printer(&printer,2);
7485                 return err;
7486         }
7487
7488         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7489                 /* Handle open failed - remove addition. */
7490                 del_a_printer(printer->info_2->sharename);
7491                 free_a_printer(&printer,2);
7492                 return WERR_ACCESS_DENIED;
7493         }
7494
7495         update_c_setprinter(False);
7496         free_a_printer(&printer,2);
7497
7498         return WERR_OK;
7499 }
7500
7501 /****************************************************************************
7502 ****************************************************************************/
7503
7504 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7505 {
7506         UNISTR2 *uni_srv_name = q_u->server_name;
7507         uint32 level = q_u->level;
7508         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7509         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7510         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7511         uint32 user_switch = q_u->user_switch;
7512         SPOOL_USER_CTR *user = &q_u->user_ctr;
7513         POLICY_HND *handle = &r_u->handle;
7514
7515         switch (level) {
7516                 case 1:
7517                         /* we don't handle yet */
7518                         /* but I know what to do ... */
7519                         return WERR_UNKNOWN_LEVEL;
7520                 case 2:
7521                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7522                                                             devmode, sdb,
7523                                                             user_switch, user, handle);
7524                 default:
7525                         return WERR_UNKNOWN_LEVEL;
7526         }
7527 }
7528
7529 /****************************************************************************
7530 ****************************************************************************/
7531
7532 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7533 {
7534         uint32 level = q_u->level;
7535         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7536         WERROR err = WERR_OK;
7537         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7538         struct current_user user;
7539         fstring driver_name;
7540         uint32 version;
7541
7542         ZERO_STRUCT(driver);
7543
7544         get_current_user(&user, p);
7545         
7546         if (!convert_printer_driver_info(info, &driver, level)) {
7547                 err = WERR_NOMEM;
7548                 goto done;
7549         }
7550
7551         DEBUG(5,("Cleaning driver's information\n"));
7552         err = clean_up_driver_struct(driver, level, &user);
7553         if (!W_ERROR_IS_OK(err))
7554                 goto done;
7555
7556         DEBUG(5,("Moving driver to final destination\n"));
7557         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7558                 goto done;
7559         }
7560
7561         if (add_a_printer_driver(driver, level)!=0) {
7562                 err = WERR_ACCESS_DENIED;
7563                 goto done;
7564         }
7565
7566         /* BEGIN_ADMIN_LOG */
7567         switch(level) {
7568             case 3:
7569                 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7570                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7571                         driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7572                 break;
7573             case 6:   
7574                 fstrcpy(driver_name, driver.info_6->name ?  driver.info_6->name : "");
7575                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7576                         driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7577                 break;
7578         }
7579         /* END_ADMIN_LOG */
7580
7581         /* 
7582          * I think this is where he DrvUpgradePrinter() hook would be
7583          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7584          * server.  Right now, we just need to send ourselves a message
7585          * to update each printer bound to this driver.   --jerry       
7586          */
7587          
7588         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7589                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7590                         driver_name));
7591         }
7592
7593         /*
7594          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7595          * decide if the driver init data should be deleted. The rules are:
7596          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7597          *  2) delete init data only if there is no 2k/Xp driver
7598          *  3) always delete init data
7599          * The generalized rule is always use init data from the highest order driver.
7600          * It is necessary to follow the driver install by an initialization step to
7601          * finish off this process.
7602         */
7603         if (level == 3)
7604                 version = driver.info_3->cversion;
7605         else if (level == 6)
7606                 version = driver.info_6->version;
7607         else
7608                 version = -1;
7609         switch (version) {
7610                 /*
7611                  * 9x printer driver - never delete init data
7612                 */
7613                 case 0: 
7614                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7615                                         driver_name));
7616                         break;
7617                 
7618                 /*
7619                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7620                  * there is no 2k/Xp driver init data for this driver name.
7621                 */
7622                 case 2:
7623                 {
7624                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7625
7626                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7627                                 /*
7628                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7629                                 */
7630                                 if (!del_driver_init(driver_name))
7631                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7632                         } else {
7633                                 /*
7634                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7635                                 */
7636                                 free_a_printer_driver(driver1,3);
7637                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", 
7638                                                 driver_name));
7639                         }
7640                 }
7641                 break;
7642
7643                 /*
7644                  * 2k or Xp printer driver - always delete init data
7645                 */
7646                 case 3: 
7647                         if (!del_driver_init(driver_name))
7648                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7649                         break;
7650
7651                 default:
7652                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7653                         break;
7654         }
7655
7656         
7657 done:
7658         free_a_printer_driver(driver, level);
7659         return err;
7660 }
7661
7662 /********************************************************************
7663  * spoolss_addprinterdriverex
7664  ********************************************************************/
7665
7666 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7667 {
7668         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7669         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7670         
7671         /* 
7672          * we only support the semantics of AddPrinterDriver()
7673          * i.e. only copy files that are newer than existing ones
7674          */
7675         
7676         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7677                 return WERR_ACCESS_DENIED;
7678         
7679         ZERO_STRUCT(q_u_local);
7680         ZERO_STRUCT(r_u_local);
7681
7682         /* just pass the information off to _spoolss_addprinterdriver() */
7683         q_u_local.server_name_ptr = q_u->server_name_ptr;
7684         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7685         q_u_local.level = q_u->level;
7686         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7687         
7688         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7689 }
7690
7691 /****************************************************************************
7692 ****************************************************************************/
7693
7694 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7695 {
7696         init_unistr(&info->name, name);
7697 }
7698
7699 /****************************************************************************
7700 ****************************************************************************/
7701
7702 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7703 {
7704         pstring path;
7705         pstring long_archi;
7706         fstring servername;
7707         char *pservername; 
7708         const char *short_archi;
7709         DRIVER_DIRECTORY_1 *info=NULL;
7710         WERROR result = WERR_OK;
7711
7712         unistr2_to_ascii(servername, name, sizeof(servername)-1);
7713         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7714
7715         /* check for beginning double '\'s and that the server
7716            long enough */
7717
7718         pservername = servername;
7719         if ( *pservername == '\\' && strlen(servername)>2 ) {
7720                 pservername += 2;
7721         } 
7722         
7723         if ( !is_myname_or_ipaddr( pservername ) )
7724                 return WERR_INVALID_PARAM;
7725
7726         if (!(short_archi = get_short_archi(long_archi)))
7727                 return WERR_INVALID_ENVIRONMENT;
7728
7729         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7730                 return WERR_NOMEM;
7731
7732         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7733
7734         DEBUG(4,("printer driver directory: [%s]\n", path));
7735
7736         fill_driverdir_1(info, path);
7737         
7738         *needed += spoolss_size_driverdir_info_1(info);
7739
7740         if (*needed > offered) {
7741                 result = WERR_INSUFFICIENT_BUFFER;
7742                 goto out;
7743         }
7744
7745         if (!rpcbuf_alloc_size(buffer, *needed)) {
7746                 result = WERR_NOMEM;
7747                 goto out;
7748         }
7749
7750         smb_io_driverdir_1("", buffer, info, 0);
7751
7752 out:
7753         SAFE_FREE(info);
7754         
7755         return result;
7756 }
7757
7758 /****************************************************************************
7759 ****************************************************************************/
7760
7761 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7762 {
7763         UNISTR2 *name = &q_u->name;
7764         UNISTR2 *uni_environment = &q_u->environment;
7765         uint32 level = q_u->level;
7766         RPC_BUFFER *buffer = NULL;
7767         uint32 offered = q_u->offered;
7768         uint32 *needed = &r_u->needed;
7769
7770         /* that's an [in out] buffer */
7771
7772         if ( q_u->buffer ) {
7773                 rpcbuf_move(q_u->buffer, &r_u->buffer);
7774                 buffer = r_u->buffer;
7775         }
7776
7777         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7778
7779         *needed=0;
7780
7781         switch(level) {
7782         case 1:
7783                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7784         default:
7785                 return WERR_UNKNOWN_LEVEL;
7786         }
7787 }
7788         
7789 /****************************************************************************
7790 ****************************************************************************/
7791
7792 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7793 {
7794         POLICY_HND *handle = &q_u->handle;
7795         uint32 idx               = q_u->index;
7796         uint32 in_value_len      = q_u->valuesize;
7797         uint32 in_data_len       = q_u->datasize;
7798         uint32 *out_max_value_len = &r_u->valuesize;
7799         uint16 **out_value       = &r_u->value;
7800         uint32 *out_value_len    = &r_u->realvaluesize;
7801         uint32 *out_type         = &r_u->type;
7802         uint32 *out_max_data_len = &r_u->datasize;
7803         uint8  **data_out        = &r_u->data;
7804         uint32 *out_data_len     = &r_u->realdatasize;
7805
7806         NT_PRINTER_INFO_LEVEL *printer = NULL;
7807         
7808         uint32          biggest_valuesize;
7809         uint32          biggest_datasize;
7810         uint32          data_len;
7811         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7812         int             snum;
7813         WERROR          result;
7814         REGISTRY_VALUE  *val = NULL;
7815         NT_PRINTER_DATA *p_data;
7816         int             i, key_index, num_values;
7817         int             name_length;
7818         
7819         *out_type = 0;
7820
7821         *out_max_data_len = 0;
7822         *data_out         = NULL;
7823         *out_data_len     = 0;
7824
7825         DEBUG(5,("spoolss_enumprinterdata\n"));
7826
7827         if (!Printer) {
7828                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7829                 return WERR_BADFID;
7830         }
7831
7832         if (!get_printer_snum(p,handle, &snum))
7833                 return WERR_BADFID;
7834         
7835         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7836         if (!W_ERROR_IS_OK(result))
7837                 return result;
7838                 
7839         p_data = printer->info_2->data; 
7840         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7841
7842         result = WERR_OK;
7843
7844         /*
7845          * The NT machine wants to know the biggest size of value and data
7846          *
7847          * cf: MSDN EnumPrinterData remark section
7848          */
7849          
7850         if ( !in_value_len && !in_data_len && (key_index != -1) ) 
7851         {
7852                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7853
7854                 biggest_valuesize = 0;
7855                 biggest_datasize  = 0;
7856                                 
7857                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7858         
7859                 for ( i=0; i<num_values; i++ )
7860                 {
7861                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7862                         
7863                         name_length = strlen(val->valuename);
7864                         if ( strlen(val->valuename) > biggest_valuesize ) 
7865                                 biggest_valuesize = name_length;
7866                                 
7867                         if ( val->size > biggest_datasize )
7868                                 biggest_datasize = val->size;
7869                                 
7870                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, 
7871                                 biggest_datasize));
7872                 }
7873
7874                 /* the value is an UNICODE string but real_value_size is the length 
7875                    in bytes including the trailing 0 */
7876                    
7877                 *out_value_len = 2 * (1+biggest_valuesize);
7878                 *out_data_len  = biggest_datasize;
7879
7880                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7881
7882                 goto done;
7883         }
7884         
7885         /*
7886          * the value len is wrong in NT sp3
7887          * that's the number of bytes not the number of unicode chars
7888          */
7889         
7890         if ( key_index != -1 )
7891                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7892
7893         if ( !val ) 
7894         {
7895
7896                 /* out_value should default to "" or else NT4 has
7897                    problems unmarshalling the response */
7898
7899                 *out_max_value_len=(in_value_len/sizeof(uint16));
7900                 
7901                 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7902                 {
7903                         result = WERR_NOMEM;
7904                         goto done;
7905                 }
7906
7907                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7908
7909                 /* the data is counted in bytes */
7910                 
7911                 *out_max_data_len = in_data_len;
7912                 *out_data_len     = in_data_len;
7913                 
7914                 /* only allocate when given a non-zero data_len */
7915                 
7916                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7917                 {
7918                         result = WERR_NOMEM;
7919                         goto done;
7920                 }
7921
7922                 result = WERR_NO_MORE_ITEMS;
7923         }
7924         else 
7925         {
7926                 /*
7927                  * the value is:
7928                  * - counted in bytes in the request
7929                  * - counted in UNICODE chars in the max reply
7930                  * - counted in bytes in the real size
7931                  *
7932                  * take a pause *before* coding not *during* coding
7933                  */
7934         
7935                 /* name */
7936                 *out_max_value_len=(in_value_len/sizeof(uint16));
7937                 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
7938                 {
7939                         result = WERR_NOMEM;
7940                         goto done;
7941                 }
7942         
7943                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7944
7945                 /* type */
7946                 
7947                 *out_type = regval_type( val );
7948
7949                 /* data - counted in bytes */
7950
7951                 *out_max_data_len = in_data_len;
7952                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
7953                 {
7954                         result = WERR_NOMEM;
7955                         goto done;
7956                 }
7957                 data_len = regval_size(val);
7958                 if ( *data_out )
7959                         memcpy( *data_out, regval_data_p(val), data_len );
7960                 *out_data_len = data_len;
7961         }
7962
7963 done:
7964         free_a_printer(&printer, 2);
7965         return result;
7966 }
7967
7968 /****************************************************************************
7969 ****************************************************************************/
7970
7971 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7972 {
7973         POLICY_HND              *handle = &q_u->handle;
7974         UNISTR2                 *value = &q_u->value;
7975         uint32                  type = q_u->type;
7976         uint8                   *data = q_u->data;
7977         uint32                  real_len = q_u->real_len;
7978
7979         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7980         int                     snum=0;
7981         WERROR                  status = WERR_OK;
7982         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
7983         fstring                 valuename;
7984         
7985         DEBUG(5,("spoolss_setprinterdata\n"));
7986
7987         if (!Printer) {
7988                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7989                 return WERR_BADFID;
7990         }
7991
7992         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7993                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7994                 return WERR_INVALID_PARAM;
7995         }
7996
7997         if (!get_printer_snum(p,handle, &snum))
7998                 return WERR_BADFID;
7999
8000         /* 
8001          * Access check : NT returns "access denied" if you make a 
8002          * SetPrinterData call without the necessary privildge.
8003          * we were originally returning OK if nothing changed
8004          * which made Win2k issue **a lot** of SetPrinterData
8005          * when connecting to a printer  --jerry
8006          */
8007
8008         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8009         {
8010                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8011                 status = WERR_ACCESS_DENIED;
8012                 goto done;
8013         }
8014
8015         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8016         if (!W_ERROR_IS_OK(status))
8017                 return status;
8018
8019         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8020         
8021         /*
8022          * When client side code sets a magic printer data key, detect it and save
8023          * the current printer data and the magic key's data (its the DEVMODE) for
8024          * future printer/driver initializations.
8025          */
8026         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
8027         {
8028                 /* Set devmode and printer initialization info */
8029                 status = save_driver_init( printer, 2, data, real_len );
8030         
8031                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8032         }
8033         else 
8034         {
8035         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
8036                                         type, data, real_len );
8037                 if ( W_ERROR_IS_OK(status) )
8038                         status = mod_a_printer(printer, 2);
8039         }
8040
8041 done:
8042         free_a_printer(&printer, 2);
8043
8044         return status;
8045 }
8046
8047 /****************************************************************************
8048 ****************************************************************************/
8049
8050 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8051 {
8052         POLICY_HND      *handle = &q_u->handle;
8053         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8054         int             snum;
8055         
8056         DEBUG(5,("_spoolss_resetprinter\n"));
8057
8058         /*
8059          * All we do is to check to see if the handle and queue is valid.
8060          * This call really doesn't mean anything to us because we only
8061          * support RAW printing.   --jerry
8062          */
8063          
8064         if (!Printer) {
8065                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8066                 return WERR_BADFID;
8067         }
8068
8069         if (!get_printer_snum(p,handle, &snum))
8070                 return WERR_BADFID;
8071
8072
8073         /* blindly return success */    
8074         return WERR_OK;
8075 }
8076
8077
8078 /****************************************************************************
8079 ****************************************************************************/
8080
8081 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8082 {
8083         POLICY_HND      *handle = &q_u->handle;
8084         UNISTR2         *value = &q_u->valuename;
8085
8086         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8087         int             snum=0;
8088         WERROR          status = WERR_OK;
8089         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8090         pstring         valuename;
8091         
8092         DEBUG(5,("spoolss_deleteprinterdata\n"));
8093         
8094         if (!Printer) {
8095                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8096                 return WERR_BADFID;
8097         }
8098
8099         if (!get_printer_snum(p, handle, &snum))
8100                 return WERR_BADFID;
8101
8102         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8103                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8104                 return WERR_ACCESS_DENIED;
8105         }
8106
8107         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8108         if (!W_ERROR_IS_OK(status))
8109                 return status;
8110
8111         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8112
8113         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8114         
8115         if ( W_ERROR_IS_OK(status) )
8116                 mod_a_printer( printer, 2 );
8117
8118         free_a_printer(&printer, 2);
8119
8120         return status;
8121 }
8122
8123 /****************************************************************************
8124 ****************************************************************************/
8125
8126 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8127 {
8128         POLICY_HND *handle = &q_u->handle;
8129         FORM *form = &q_u->form;
8130         nt_forms_struct tmpForm;
8131         int snum;
8132         WERROR status = WERR_OK;
8133         NT_PRINTER_INFO_LEVEL *printer = NULL;
8134
8135         int count=0;
8136         nt_forms_struct *list=NULL;
8137         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8138
8139         DEBUG(5,("spoolss_addform\n"));
8140
8141         if (!Printer) {
8142                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8143                 return WERR_BADFID;
8144         }
8145         
8146         
8147         /* forms can be added on printer of on the print server handle */
8148         
8149         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8150         {
8151                 if (!get_printer_snum(p,handle, &snum))
8152                         return WERR_BADFID;
8153          
8154                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8155                 if (!W_ERROR_IS_OK(status))
8156                         goto done;
8157         }
8158
8159         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8160                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8161                 status = WERR_ACCESS_DENIED;
8162                 goto done;
8163         }
8164         
8165         /* can't add if builtin */
8166         
8167         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8168                 status = WERR_ALREADY_EXISTS;
8169                 goto done;
8170         }
8171
8172         count = get_ntforms(&list);
8173         
8174         if(!add_a_form(&list, form, &count)) {
8175                 status =  WERR_NOMEM;
8176                 goto done;
8177         }
8178         
8179         write_ntforms(&list, count);
8180         
8181         /*
8182          * ChangeID must always be set if this is a printer
8183          */
8184          
8185         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8186                 status = mod_a_printer(printer, 2);
8187         
8188 done:
8189         if ( printer )
8190                 free_a_printer(&printer, 2);
8191         SAFE_FREE(list);
8192
8193         return status;
8194 }
8195
8196 /****************************************************************************
8197 ****************************************************************************/
8198
8199 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8200 {
8201         POLICY_HND *handle = &q_u->handle;
8202         UNISTR2 *form_name = &q_u->name;
8203         nt_forms_struct tmpForm;
8204         int count=0;
8205         nt_forms_struct *list=NULL;
8206         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8207         int snum;
8208         WERROR status = WERR_OK;
8209         NT_PRINTER_INFO_LEVEL *printer = NULL;
8210
8211         DEBUG(5,("spoolss_deleteform\n"));
8212
8213         if (!Printer) {
8214                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8215                 return WERR_BADFID;
8216         }
8217
8218         /* forms can be deleted on printer of on the print server handle */
8219         
8220         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8221         {
8222                 if (!get_printer_snum(p,handle, &snum))
8223                         return WERR_BADFID;
8224          
8225                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8226                 if (!W_ERROR_IS_OK(status))
8227                         goto done;
8228         }
8229
8230         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8231                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8232                 status = WERR_ACCESS_DENIED;
8233                 goto done;
8234         }
8235
8236         /* can't delete if builtin */
8237         
8238         if (get_a_builtin_ntform(form_name,&tmpForm)) {
8239                 status = WERR_INVALID_PARAM;
8240                 goto done;
8241         }
8242
8243         count = get_ntforms(&list);
8244         
8245         if ( !delete_a_form(&list, form_name, &count, &status ))
8246                 goto done;
8247
8248         /*
8249          * ChangeID must always be set if this is a printer
8250          */
8251          
8252         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8253                 status = mod_a_printer(printer, 2);
8254         
8255 done:
8256         if ( printer )
8257                 free_a_printer(&printer, 2);
8258         SAFE_FREE(list);
8259
8260         return status;
8261 }
8262
8263 /****************************************************************************
8264 ****************************************************************************/
8265
8266 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8267 {
8268         POLICY_HND *handle = &q_u->handle;
8269         FORM *form = &q_u->form;
8270         nt_forms_struct tmpForm;
8271         int snum;
8272         WERROR status = WERR_OK;
8273         NT_PRINTER_INFO_LEVEL *printer = NULL;
8274
8275         int count=0;
8276         nt_forms_struct *list=NULL;
8277         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8278
8279         DEBUG(5,("spoolss_setform\n"));
8280
8281         if (!Printer) {
8282                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8283                 return WERR_BADFID;
8284         }
8285
8286         /* forms can be modified on printer of on the print server handle */
8287         
8288         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8289         {
8290                 if (!get_printer_snum(p,handle, &snum))
8291                         return WERR_BADFID;
8292          
8293                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8294                 if (!W_ERROR_IS_OK(status))
8295                         goto done;
8296         }
8297
8298         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8299                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8300                 status = WERR_ACCESS_DENIED;
8301                 goto done;
8302         }
8303
8304         /* can't set if builtin */
8305         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8306                 status = WERR_INVALID_PARAM;
8307                 goto done;
8308         }
8309
8310         count = get_ntforms(&list);
8311         update_a_form(&list, form, count);
8312         write_ntforms(&list, count);
8313
8314         /*
8315          * ChangeID must always be set if this is a printer
8316          */
8317          
8318         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8319                 status = mod_a_printer(printer, 2);
8320         
8321         
8322 done:
8323         if ( printer )
8324                 free_a_printer(&printer, 2);
8325         SAFE_FREE(list);
8326
8327         return status;
8328 }
8329
8330 /****************************************************************************
8331  enumprintprocessors level 1.
8332 ****************************************************************************/
8333
8334 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8335 {
8336         PRINTPROCESSOR_1 *info_1=NULL;
8337         WERROR result = WERR_OK;
8338         
8339         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8340                 return WERR_NOMEM;
8341
8342         (*returned) = 0x1;
8343         
8344         init_unistr(&info_1->name, "winprint");
8345
8346         *needed += spoolss_size_printprocessor_info_1(info_1);
8347
8348         if (*needed > offered) {
8349                 result = WERR_INSUFFICIENT_BUFFER;
8350                 goto out;
8351         }
8352
8353         if (!rpcbuf_alloc_size(buffer, *needed)) {
8354                 result = WERR_NOMEM;
8355                 goto out;
8356         }
8357
8358         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8359
8360 out:
8361         SAFE_FREE(info_1);
8362
8363         if ( !W_ERROR_IS_OK(result) )
8364                 *returned = 0;
8365
8366         return result;
8367 }
8368
8369 /****************************************************************************
8370 ****************************************************************************/
8371
8372 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8373 {
8374         uint32 level = q_u->level;
8375         RPC_BUFFER *buffer = NULL;
8376         uint32 offered = q_u->offered;
8377         uint32 *needed = &r_u->needed;
8378         uint32 *returned = &r_u->returned;
8379
8380         /* that's an [in out] buffer */
8381
8382         if ( q_u->buffer ) {
8383                 rpcbuf_move(q_u->buffer, &r_u->buffer);
8384                 buffer = r_u->buffer;
8385         }
8386
8387         DEBUG(5,("spoolss_enumprintprocessors\n"));
8388
8389         /*
8390          * Enumerate the print processors ...
8391          *
8392          * Just reply with "winprint", to keep NT happy
8393          * and I can use my nice printer checker.
8394          */
8395         
8396         *returned=0;
8397         *needed=0;
8398         
8399         switch (level) {
8400         case 1:
8401                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8402         default:
8403                 return WERR_UNKNOWN_LEVEL;
8404         }
8405 }
8406
8407 /****************************************************************************
8408  enumprintprocdatatypes level 1.
8409 ****************************************************************************/
8410
8411 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8412 {
8413         PRINTPROCDATATYPE_1 *info_1=NULL;
8414         WERROR result = WERR_NOMEM;
8415         
8416         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8417                 return WERR_NOMEM;
8418
8419         (*returned) = 0x1;
8420         
8421         init_unistr(&info_1->name, "RAW");
8422
8423         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8424
8425         if (*needed > offered) {
8426                 result = WERR_INSUFFICIENT_BUFFER;
8427                 goto out;
8428         }
8429
8430         if (!rpcbuf_alloc_size(buffer, *needed)) {
8431                 result = WERR_NOMEM;
8432                 goto out;
8433         }
8434
8435         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8436
8437 out:
8438         SAFE_FREE(info_1);
8439
8440         if ( !W_ERROR_IS_OK(result) )
8441                 *returned = 0;
8442
8443         return result;
8444 }
8445
8446 /****************************************************************************
8447 ****************************************************************************/
8448
8449 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8450 {
8451         uint32 level = q_u->level;
8452         RPC_BUFFER *buffer = NULL;
8453         uint32 offered = q_u->offered;
8454         uint32 *needed = &r_u->needed;
8455         uint32 *returned = &r_u->returned;
8456
8457         /* that's an [in out] buffer */
8458
8459         if ( q_u->buffer ) {
8460                 rpcbuf_move(q_u->buffer, &r_u->buffer);
8461                 buffer = r_u->buffer;
8462         }
8463
8464         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8465         
8466         *returned=0;
8467         *needed=0;
8468         
8469         switch (level) {
8470         case 1:
8471                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8472         default:
8473                 return WERR_UNKNOWN_LEVEL;
8474         }
8475 }
8476
8477 /****************************************************************************
8478  enumprintmonitors level 1.
8479 ****************************************************************************/
8480
8481 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8482 {
8483         PRINTMONITOR_1 *info_1=NULL;
8484         WERROR result = WERR_OK;
8485         
8486         if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8487                 return WERR_NOMEM;
8488
8489         (*returned) = 0x1;
8490         
8491         init_unistr(&info_1->name, "Local Port");
8492
8493         *needed += spoolss_size_printmonitor_info_1(info_1);
8494
8495         if (*needed > offered) {
8496                 result = WERR_INSUFFICIENT_BUFFER;
8497                 goto out;
8498         }
8499
8500         if (!rpcbuf_alloc_size(buffer, *needed)) {
8501                 result = WERR_NOMEM;
8502                 goto out;
8503         }
8504
8505         smb_io_printmonitor_info_1("", buffer, info_1, 0);
8506
8507 out:
8508         SAFE_FREE(info_1);
8509
8510         if ( !W_ERROR_IS_OK(result) )
8511                 *returned = 0;
8512
8513         return result;
8514 }
8515
8516 /****************************************************************************
8517  enumprintmonitors level 2.
8518 ****************************************************************************/
8519
8520 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8521 {
8522         PRINTMONITOR_2 *info_2=NULL;
8523         WERROR result = WERR_OK;
8524         
8525         if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8526                 return WERR_NOMEM;
8527
8528         (*returned) = 0x1;
8529         
8530         init_unistr(&info_2->name, "Local Port");
8531         init_unistr(&info_2->environment, "Windows NT X86");
8532         init_unistr(&info_2->dll_name, "localmon.dll");
8533
8534         *needed += spoolss_size_printmonitor_info_2(info_2);
8535
8536         if (*needed > offered) {
8537                 result = WERR_INSUFFICIENT_BUFFER;
8538                 goto out;
8539         }
8540
8541         if (!rpcbuf_alloc_size(buffer, *needed)) {
8542                 result = WERR_NOMEM;
8543                 goto out;
8544         }
8545
8546         smb_io_printmonitor_info_2("", buffer, info_2, 0);
8547
8548 out:
8549         SAFE_FREE(info_2);
8550
8551         if ( !W_ERROR_IS_OK(result) )
8552                 *returned = 0;
8553         
8554         return result;
8555 }
8556
8557 /****************************************************************************
8558 ****************************************************************************/
8559
8560 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8561 {
8562         uint32 level = q_u->level;
8563         RPC_BUFFER *buffer = NULL;
8564         uint32 offered = q_u->offered;
8565         uint32 *needed = &r_u->needed;
8566         uint32 *returned = &r_u->returned;
8567
8568         /* that's an [in out] buffer */
8569
8570         if ( q_u->buffer ) {
8571                 rpcbuf_move(q_u->buffer, &r_u->buffer);
8572                 buffer = r_u->buffer;
8573         }
8574
8575         DEBUG(5,("spoolss_enumprintmonitors\n"));
8576
8577         /*
8578          * Enumerate the print monitors ...
8579          *
8580          * Just reply with "Local Port", to keep NT happy
8581          * and I can use my nice printer checker.
8582          */
8583         
8584         *returned=0;
8585         *needed=0;
8586         
8587         switch (level) {
8588         case 1:
8589                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8590         case 2:
8591                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8592         default:
8593                 return WERR_UNKNOWN_LEVEL;
8594         }
8595 }
8596
8597 /****************************************************************************
8598 ****************************************************************************/
8599
8600 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8601                              NT_PRINTER_INFO_LEVEL *ntprinter,
8602                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered, 
8603                              uint32 *needed)
8604 {
8605         int i=0;
8606         BOOL found=False;
8607         JOB_INFO_1 *info_1=NULL;
8608         WERROR result = WERR_OK;
8609
8610         info_1=SMB_MALLOC_P(JOB_INFO_1);
8611
8612         if (info_1 == NULL) {
8613                 return WERR_NOMEM;
8614         }
8615                 
8616         for (i=0; i<count && found==False; i++) { 
8617                 if ((*queue)[i].job==(int)jobid)
8618                         found=True;
8619         }
8620         
8621         if (found==False) {
8622                 SAFE_FREE(info_1);
8623                 /* NT treats not found as bad param... yet another bad choice */
8624                 return WERR_INVALID_PARAM;
8625         }
8626         
8627         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8628         
8629         *needed += spoolss_size_job_info_1(info_1);
8630
8631         if (*needed > offered) {
8632                 result = WERR_INSUFFICIENT_BUFFER;
8633                 goto out;
8634         }
8635
8636         if (!rpcbuf_alloc_size(buffer, *needed)) {
8637                 result = WERR_NOMEM;
8638                 goto out;
8639         }
8640
8641         smb_io_job_info_1("", buffer, info_1, 0);
8642
8643 out:
8644         SAFE_FREE(info_1);
8645
8646         return result;
8647 }
8648
8649 /****************************************************************************
8650 ****************************************************************************/
8651
8652 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, 
8653                              NT_PRINTER_INFO_LEVEL *ntprinter,
8654                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered, 
8655                              uint32 *needed)
8656 {
8657         int             i = 0;
8658         BOOL            found = False;
8659         JOB_INFO_2      *info_2;
8660         WERROR          result;
8661         DEVICEMODE      *devmode = NULL;
8662         NT_DEVICEMODE   *nt_devmode = NULL;
8663
8664         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8665                 return WERR_NOMEM;
8666
8667         ZERO_STRUCTP(info_2);
8668
8669         for ( i=0; i<count && found==False; i++ ) 
8670         {
8671                 if ((*queue)[i].job == (int)jobid)
8672                         found = True;
8673         }
8674         
8675         if ( !found ) {
8676                 /* NT treats not found as bad param... yet another bad
8677                    choice */
8678                 result = WERR_INVALID_PARAM;
8679                 goto done;
8680         }
8681         
8682         /* 
8683          * if the print job does not have a DEVMODE associated with it, 
8684          * just use the one for the printer. A NULL devicemode is not
8685          *  a failure condition
8686          */
8687          
8688         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8689                 devmode = construct_dev_mode(snum);
8690         else {
8691                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8692                         ZERO_STRUCTP( devmode );
8693                         convert_nt_devicemode( devmode, nt_devmode );
8694                 }
8695         }
8696         
8697         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8698         
8699         *needed += spoolss_size_job_info_2(info_2);
8700
8701         if (*needed > offered) {
8702                 result = WERR_INSUFFICIENT_BUFFER;
8703                 goto done;
8704         }
8705
8706         if (!rpcbuf_alloc_size(buffer, *needed)) {
8707                 result = WERR_NOMEM;
8708                 goto done;
8709         }
8710
8711         smb_io_job_info_2("", buffer, info_2, 0);
8712
8713         result = WERR_OK;
8714         
8715  done:
8716         /* Cleanup allocated memory */
8717
8718         free_job_info_2(info_2);        /* Also frees devmode */
8719         SAFE_FREE(info_2);
8720
8721         return result;
8722 }
8723
8724 /****************************************************************************
8725 ****************************************************************************/
8726
8727 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8728 {
8729         POLICY_HND *handle = &q_u->handle;
8730         uint32 jobid = q_u->jobid;
8731         uint32 level = q_u->level;
8732         RPC_BUFFER *buffer = NULL;
8733         uint32 offered = q_u->offered;
8734         uint32 *needed = &r_u->needed;
8735         WERROR          wstatus = WERR_OK;
8736         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8737         int snum;
8738         int count;
8739         print_queue_struct      *queue = NULL;
8740         print_status_struct prt_status;
8741
8742         /* that's an [in out] buffer */
8743
8744         if ( q_u->buffer ) {
8745                 rpcbuf_move(q_u->buffer, &r_u->buffer);
8746                 buffer = r_u->buffer;
8747         }
8748
8749         DEBUG(5,("spoolss_getjob\n"));
8750         
8751         *needed = 0;
8752         
8753         if (!get_printer_snum(p, handle, &snum))
8754                 return WERR_BADFID;
8755         
8756         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8757         if ( !W_ERROR_IS_OK(wstatus) )
8758                 return wstatus;
8759                 
8760         count = print_queue_status(snum, &queue, &prt_status);
8761         
8762         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8763                      count, prt_status.status, prt_status.message));
8764                 
8765         switch ( level ) {
8766         case 1:
8767                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid, 
8768                                 buffer, offered, needed);
8769                         break;
8770         case 2:
8771                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid, 
8772                                 buffer, offered, needed);
8773                         break;
8774         default:
8775                         wstatus = WERR_UNKNOWN_LEVEL;
8776                         break;
8777         }
8778         
8779         SAFE_FREE(queue);
8780         free_a_printer( &ntprinter, 2 );
8781         
8782         return wstatus;
8783 }
8784
8785 /********************************************************************
8786  spoolss_getprinterdataex
8787  
8788  From MSDN documentation of GetPrinterDataEx: pass request
8789  to GetPrinterData if key is "PrinterDriverData".
8790  ********************************************************************/
8791
8792 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8793 {
8794         POLICY_HND      *handle = &q_u->handle;
8795         uint32          in_size = q_u->size;
8796         uint32          *type = &r_u->type;
8797         uint32          *out_size = &r_u->size;
8798         uint8           **data = &r_u->data;
8799         uint32          *needed = &r_u->needed;
8800         fstring         keyname, valuename;
8801         
8802         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8803         
8804         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8805         int                     snum = 0;
8806         WERROR                  status = WERR_OK;
8807
8808         DEBUG(4,("_spoolss_getprinterdataex\n"));
8809
8810         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8811         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8812         
8813         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
8814                 keyname, valuename));
8815
8816         /* in case of problem, return some default values */
8817         
8818         *needed   = 0;
8819         *type     = 0;
8820         *out_size = in_size;
8821
8822         if (!Printer) {
8823                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8824                 status = WERR_BADFID;
8825                 goto done;
8826         }
8827
8828         /* Is the handle to a printer or to the server? */
8829
8830         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8831                 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8832                 status = WERR_INVALID_PARAM;
8833                 goto done;
8834         }
8835         
8836         if ( !get_printer_snum(p,handle, &snum) )
8837                 return WERR_BADFID;
8838
8839         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8840         if ( !W_ERROR_IS_OK(status) )
8841                 goto done;
8842
8843         /* check to see if the keyname is valid */
8844         if ( !strlen(keyname) ) {
8845                 status = WERR_INVALID_PARAM;
8846                 goto done;
8847         }
8848         
8849         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8850                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8851                 free_a_printer( &printer, 2 );
8852                 status = WERR_BADFILE;
8853                 goto done;
8854         }
8855         
8856         /* When given a new keyname, we should just create it */
8857
8858         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8859         
8860         if (*needed > *out_size)
8861                 status = WERR_MORE_DATA;
8862
8863 done:
8864         if ( !W_ERROR_IS_OK(status) ) 
8865         {
8866                 DEBUG(5, ("error: allocating %d\n", *out_size));
8867                 
8868                 /* reply this param doesn't exist */
8869                 
8870                 if ( *out_size ) 
8871                 {
8872                         if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8873                                 status = WERR_NOMEM;
8874                                 goto done;
8875                         }
8876                 } 
8877                 else {
8878                         *data = NULL;
8879         }
8880         }
8881         
8882         if ( printer )
8883         free_a_printer( &printer, 2 );
8884         
8885         return status;
8886 }
8887
8888 /********************************************************************
8889  * spoolss_setprinterdataex
8890  ********************************************************************/
8891
8892 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8893 {
8894         POLICY_HND              *handle = &q_u->handle; 
8895         uint32                  type = q_u->type;
8896         uint8                   *data = q_u->data;
8897         uint32                  real_len = q_u->real_len;
8898
8899         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8900         int                     snum = 0;
8901         WERROR                  status = WERR_OK;
8902         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
8903         fstring                 valuename;
8904         fstring                 keyname;
8905         char                    *oid_string;
8906         
8907         DEBUG(4,("_spoolss_setprinterdataex\n"));
8908
8909         /* From MSDN documentation of SetPrinterDataEx: pass request to
8910            SetPrinterData if key is "PrinterDriverData" */
8911
8912         if (!Printer) {
8913                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8914                 return WERR_BADFID;
8915         }
8916
8917         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8918                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8919                 return WERR_INVALID_PARAM;
8920         }
8921
8922         if ( !get_printer_snum(p,handle, &snum) )
8923                 return WERR_BADFID;
8924
8925         /* 
8926          * Access check : NT returns "access denied" if you make a 
8927          * SetPrinterData call without the necessary privildge.
8928          * we were originally returning OK if nothing changed
8929          * which made Win2k issue **a lot** of SetPrinterData
8930          * when connecting to a printer  --jerry
8931          */
8932
8933         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8934         {
8935                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8936                 return WERR_ACCESS_DENIED;
8937         }
8938
8939         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8940         if (!W_ERROR_IS_OK(status))
8941                 return status;
8942
8943         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8944         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8945         
8946         /* check for OID in valuename */
8947         
8948         if ( (oid_string = strchr( valuename, ',' )) != NULL )
8949         {
8950                 *oid_string = '\0';
8951                 oid_string++;
8952         }
8953
8954         /* save the registry data */
8955         
8956         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
8957         
8958         if ( W_ERROR_IS_OK(status) )
8959         {
8960                 /* save the OID if one was specified */
8961                 if ( oid_string ) {
8962                         fstrcat( keyname, "\\" );
8963                         fstrcat( keyname, SPOOL_OID_KEY );
8964                 
8965                         /* 
8966                          * I'm not checking the status here on purpose.  Don't know 
8967                          * if this is right, but I'm returning the status from the 
8968                          * previous set_printer_dataex() call.  I have no idea if 
8969                          * this is right.    --jerry
8970                          */
8971                  
8972                         set_printer_dataex( printer, keyname, valuename, 
8973                                             REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
8974                 }
8975         
8976                 status = mod_a_printer(printer, 2);
8977         }
8978                 
8979         free_a_printer(&printer, 2);
8980
8981         return status;
8982 }
8983
8984
8985 /********************************************************************
8986  * spoolss_deleteprinterdataex
8987  ********************************************************************/
8988
8989 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8990 {
8991         POLICY_HND      *handle = &q_u->handle;
8992         UNISTR2         *value = &q_u->valuename;
8993         UNISTR2         *key = &q_u->keyname;
8994
8995         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8996         int             snum=0;
8997         WERROR          status = WERR_OK;
8998         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8999         pstring         valuename, keyname;
9000         
9001         DEBUG(5,("spoolss_deleteprinterdataex\n"));
9002         
9003         if (!Printer) {
9004                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9005                 return WERR_BADFID;
9006         }
9007
9008         if (!get_printer_snum(p, handle, &snum))
9009                 return WERR_BADFID;
9010
9011         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9012                 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9013                 return WERR_ACCESS_DENIED;
9014         }
9015
9016         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9017         if (!W_ERROR_IS_OK(status))
9018                 return status;
9019
9020         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9021         unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9022
9023         status = delete_printer_dataex( printer, keyname, valuename );
9024
9025         if ( W_ERROR_IS_OK(status) )
9026                 mod_a_printer( printer, 2 );
9027                 
9028         free_a_printer(&printer, 2);
9029
9030         return status;
9031 }
9032
9033 /********************************************************************
9034  * spoolss_enumprinterkey
9035  ********************************************************************/
9036
9037
9038 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9039 {
9040         fstring         key;
9041         fstring         *keynames = NULL;
9042         uint16          *enumkeys = NULL;
9043         int             num_keys;
9044         int             printerkey_len;
9045         POLICY_HND      *handle = &q_u->handle;
9046         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9047         NT_PRINTER_DATA *data;
9048         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9049         int             snum = 0;
9050         WERROR          status = WERR_BADFILE;
9051         
9052         
9053         DEBUG(4,("_spoolss_enumprinterkey\n"));
9054
9055         if (!Printer) {
9056                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9057                 return WERR_BADFID;
9058         }
9059
9060         if ( !get_printer_snum(p,handle, &snum) )
9061                 return WERR_BADFID;
9062
9063         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9064         if (!W_ERROR_IS_OK(status))
9065                 return status;
9066                 
9067         /* get the list of subkey names */
9068         
9069         unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9070         data = printer->info_2->data;
9071
9072         num_keys = get_printer_subkeys( data, key, &keynames );
9073
9074         if ( num_keys == -1 ) {
9075                 status = WERR_BADFILE;
9076                 goto done;
9077         }
9078
9079         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9080
9081         r_u->needed = printerkey_len*2;
9082
9083         if ( q_u->size < r_u->needed ) {
9084                 status = WERR_MORE_DATA;
9085                 goto done;
9086         }
9087
9088         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9089                 status = WERR_NOMEM;
9090                 goto done;
9091         }
9092                         
9093         status = WERR_OK;
9094
9095         if ( q_u->size < r_u->needed ) 
9096                 status = WERR_MORE_DATA;
9097
9098 done:
9099         free_a_printer( &printer, 2 );
9100         SAFE_FREE( keynames );
9101         
9102         return status;
9103 }
9104
9105 /********************************************************************
9106  * spoolss_deleteprinterkey
9107  ********************************************************************/
9108
9109 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9110 {
9111         POLICY_HND              *handle = &q_u->handle;
9112         Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9113         fstring                 key;
9114         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9115         int                     snum=0;
9116         WERROR                  status;
9117         
9118         DEBUG(5,("spoolss_deleteprinterkey\n"));
9119         
9120         if (!Printer) {
9121                 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9122                 return WERR_BADFID;
9123         }
9124
9125         /* if keyname == NULL, return error */
9126         
9127         if ( !q_u->keyname.buffer )
9128                 return WERR_INVALID_PARAM;
9129                 
9130         if (!get_printer_snum(p, handle, &snum))
9131                 return WERR_BADFID;
9132
9133         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9134                 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9135                 return WERR_ACCESS_DENIED;
9136         }
9137
9138         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9139         if (!W_ERROR_IS_OK(status))
9140                 return status;
9141         
9142         /* delete the key and all subneys */
9143         
9144         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9145  
9146         status = delete_all_printer_data( printer->info_2, key );       
9147
9148         if ( W_ERROR_IS_OK(status) )
9149                 status = mod_a_printer(printer, 2);
9150         
9151         free_a_printer( &printer, 2 );
9152         
9153         return status;
9154 }
9155
9156
9157 /********************************************************************
9158  * spoolss_enumprinterdataex
9159  ********************************************************************/
9160
9161 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9162 {
9163         POLICY_HND      *handle = &q_u->handle; 
9164         uint32          in_size = q_u->size;
9165         uint32          num_entries, 
9166                         needed;
9167         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9168         PRINTER_ENUM_VALUES     *enum_values = NULL;
9169         NT_PRINTER_DATA         *p_data;
9170         fstring         key;
9171         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9172         int             snum;
9173         WERROR          result;
9174         int             key_index;
9175         int             i;
9176         REGISTRY_VALUE  *val;
9177         char            *value_name;
9178         uint32          data_len;
9179         
9180
9181         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9182
9183         if (!Printer) {
9184                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9185                 return WERR_BADFID;
9186         }
9187
9188         /* 
9189          * first check for a keyname of NULL or "".  Win2k seems to send 
9190          * this a lot and we should send back WERR_INVALID_PARAM
9191          * no need to spend time looking up the printer in this case.
9192          * --jerry
9193          */
9194          
9195         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9196         if ( !strlen(key) ) {
9197                 result = WERR_INVALID_PARAM;
9198                 goto done;
9199         }
9200
9201         /* get the printer off of disk */
9202         
9203         if (!get_printer_snum(p,handle, &snum))
9204                 return WERR_BADFID;
9205         
9206         ZERO_STRUCT(printer);
9207         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9208         if (!W_ERROR_IS_OK(result))
9209                 return result;
9210         
9211         /* now look for a match on the key name */
9212         
9213         p_data = printer->info_2->data;
9214         
9215         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9216         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9217         {
9218                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9219                 result = WERR_INVALID_PARAM;
9220                 goto done;
9221         }
9222         
9223         result = WERR_OK;
9224         needed = 0;
9225         
9226         /* allocate the memory for the array of pointers -- if necessary */
9227         
9228         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9229         if ( num_entries )
9230         {
9231                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9232                 {
9233                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9234                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9235                         result = WERR_NOMEM;
9236                         goto done;
9237                 }
9238
9239                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9240         }
9241                 
9242         /* 
9243          * loop through all params and build the array to pass 
9244          * back to the  client 
9245          */
9246          
9247         for ( i=0; i<num_entries; i++ )
9248         {
9249                 /* lookup the registry value */
9250                 
9251                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9252                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9253
9254                 /* copy the data */
9255                 
9256                 value_name = regval_name( val );
9257                 init_unistr( &enum_values[i].valuename, value_name );
9258                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9259                 enum_values[i].type      = regval_type( val );
9260                 
9261                 data_len = regval_size( val );
9262                 if ( data_len ) {
9263                         if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) ) 
9264                         {
9265                                 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", 
9266                                         data_len ));
9267                                 result = WERR_NOMEM;
9268                                 goto done;
9269                         }
9270                 }
9271                 enum_values[i].data_len = data_len;
9272
9273                 /* keep track of the size of the array in bytes */
9274                 
9275                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9276         }
9277         
9278         /* housekeeping information in the reply */
9279         
9280         r_u->needed     = needed;
9281         r_u->returned   = num_entries;
9282
9283         if (needed > in_size) {
9284                 result = WERR_MORE_DATA;
9285                 goto done;
9286         }
9287                 
9288         /* copy data into the reply */
9289         
9290         r_u->ctr.size           = r_u->needed;
9291         r_u->ctr.size_of_array  = r_u->returned;
9292         r_u->ctr.values         = enum_values;
9293         
9294         
9295                 
9296 done:   
9297         if ( printer )
9298         free_a_printer(&printer, 2);
9299
9300         return result;
9301 }
9302
9303 /****************************************************************************
9304 ****************************************************************************/
9305
9306 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9307 {
9308         init_unistr(&info->name, name);
9309 }
9310
9311 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
9312                                                  UNISTR2 *environment, 
9313                                                  RPC_BUFFER *buffer, 
9314                                                  uint32 offered, 
9315                                                  uint32 *needed)
9316 {
9317         pstring path;
9318         pstring long_archi;
9319         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9320         WERROR result = WERR_OK;
9321
9322         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9323
9324         if (!get_short_archi(long_archi))
9325                 return WERR_INVALID_ENVIRONMENT;
9326
9327         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9328                 return WERR_NOMEM;
9329
9330         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9331
9332         fill_printprocessordirectory_1(info, path);
9333         
9334         *needed += spoolss_size_printprocessordirectory_info_1(info);
9335
9336         if (*needed > offered) {
9337                 result = WERR_INSUFFICIENT_BUFFER;
9338                 goto out;
9339         }
9340
9341         if (!rpcbuf_alloc_size(buffer, *needed)) {
9342                 result = WERR_INSUFFICIENT_BUFFER;
9343                 goto out;
9344         }
9345
9346         smb_io_printprocessordirectory_1("", buffer, info, 0);
9347
9348 out:
9349         SAFE_FREE(info);
9350         
9351         return result;
9352 }
9353
9354 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9355 {
9356         uint32 level = q_u->level;
9357         RPC_BUFFER *buffer = NULL;
9358         uint32 offered = q_u->offered;
9359         uint32 *needed = &r_u->needed;
9360         WERROR result;
9361
9362         /* that's an [in out] buffer */
9363
9364         if ( q_u->buffer ) {
9365                 rpcbuf_move(q_u->buffer, &r_u->buffer);
9366                 buffer = r_u->buffer;
9367         }
9368
9369         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9370         
9371         *needed=0;
9372
9373         switch(level) {
9374         case 1:
9375                 result = getprintprocessordirectory_level_1
9376                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9377                 break;
9378         default:
9379                 result = WERR_UNKNOWN_LEVEL;
9380         }
9381
9382         return result;
9383 }
9384
9385 #if 0
9386
9387 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u, 
9388                                  SPOOL_R_REPLYOPENPRINTER *r_u)
9389 {
9390         DEBUG(5,("_spoolss_replyopenprinter\n"));
9391
9392         DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9393
9394         return WERR_OK;
9395 }
9396
9397 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u, 
9398                                   SPOOL_R_REPLYCLOSEPRINTER *r_u)
9399 {
9400         DEBUG(5,("_spoolss_replycloseprinter\n"));
9401         return WERR_OK;
9402 }
9403
9404 #endif