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