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