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