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