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