r14482: Fixes for spoolss code (after coverity fixes) when the
[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)/sizeof(struct s_notify_info_data_table)); i++) {
3445                 if ( (notify_info_data_table[i].type == type)
3446                         && (notify_info_data_table[i].field == field) ) {
3447                         switch(notify_info_data_table[i].size) {
3448                                 case NOTIFY_ONE_VALUE:
3449                                 case NOTIFY_TWO_VALUE:
3450                                         return 1;
3451                                 case NOTIFY_STRING:
3452                                         return 2;
3453
3454                                 /* The only pointer notify data I have seen on
3455                                    the wire is the submitted time and this has
3456                                    the notify size set to 4. -tpot */
3457
3458                                 case NOTIFY_POINTER:
3459                                         return 4;
3460                                         
3461                                 case NOTIFY_SECDESC:
3462                                         return 5;
3463                         }
3464                 }
3465         }
3466
3467         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3468
3469         return 0;
3470 }
3471
3472 /*******************************************************************
3473  Return the type of notify_info_data.
3474 ********************************************************************/
3475
3476 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3477 {
3478         uint32 i=0;
3479
3480         for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3481                 if (notify_info_data_table[i].type == type &&
3482                     notify_info_data_table[i].field == field)
3483                         return notify_info_data_table[i].size;
3484         }
3485
3486         return 0;
3487 }
3488
3489 /****************************************************************************
3490 ****************************************************************************/
3491
3492 static BOOL search_notify(uint16 type, uint16 field, int *value)
3493 {       
3494         int i;
3495
3496         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3497                 if (notify_info_data_table[i].type == type &&
3498                     notify_info_data_table[i].field == field &&
3499                     notify_info_data_table[i].fn != NULL) {
3500                         *value = i;
3501                         return True;
3502                 }
3503         }
3504         
3505         return False;   
3506 }
3507
3508 /****************************************************************************
3509 ****************************************************************************/
3510
3511 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3512 {
3513         info_data->type     = type;
3514         info_data->field    = field;
3515         info_data->reserved = 0;
3516
3517         info_data->size     = size_of_notify_info_data(type, field);
3518         info_data->enc_type = type_of_notify_info_data(type, field);
3519
3520         info_data->id = id;
3521 }
3522
3523 /*******************************************************************
3524  *
3525  * fill a notify_info struct with info asked
3526  *
3527  ********************************************************************/
3528
3529 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3530                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3531                                           *option_type, uint32 id,
3532                                           TALLOC_CTX *mem_ctx) 
3533 {
3534         int field_num,j;
3535         uint16 type;
3536         uint16 field;
3537
3538         SPOOL_NOTIFY_INFO_DATA *current_data;
3539         NT_PRINTER_INFO_LEVEL *printer = NULL;
3540         print_queue_struct *queue=NULL;
3541
3542         type=option_type->type;
3543
3544         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3545                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3546                 option_type->count, lp_servicename(snum)));
3547         
3548         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3549                 return False;
3550
3551         for(field_num=0; field_num<option_type->count; field_num++) {
3552                 field = option_type->fields[field_num];
3553                 
3554                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3555
3556                 if (!search_notify(type, field, &j) )
3557                         continue;
3558
3559                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3560                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3561                         return False;
3562                 }
3563
3564                 current_data = &info->data[info->count];
3565
3566                 construct_info_data(current_data, type, field, id);
3567
3568                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3569                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3570
3571                 notify_info_data_table[j].fn(snum, current_data, queue,
3572                                              printer, mem_ctx);
3573
3574                 info->count++;
3575         }
3576
3577         free_a_printer(&printer, 2);
3578         return True;
3579 }
3580
3581 /*******************************************************************
3582  *
3583  * fill a notify_info struct with info asked
3584  *
3585  ********************************************************************/
3586
3587 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3588                                        SPOOL_NOTIFY_INFO *info,
3589                                        NT_PRINTER_INFO_LEVEL *printer,
3590                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3591                                        *option_type, uint32 id,
3592                                        TALLOC_CTX *mem_ctx) 
3593 {
3594         int field_num,j;
3595         uint16 type;
3596         uint16 field;
3597
3598         SPOOL_NOTIFY_INFO_DATA *current_data;
3599         
3600         DEBUG(4,("construct_notify_jobs_info\n"));
3601         
3602         type = option_type->type;
3603
3604         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3605                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3606                 option_type->count));
3607
3608         for(field_num=0; field_num<option_type->count; field_num++) {
3609                 field = option_type->fields[field_num];
3610
3611                 if (!search_notify(type, field, &j) )
3612                         continue;
3613
3614                 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3615                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3616                         return False;
3617                 }
3618
3619                 current_data=&(info->data[info->count]);
3620
3621                 construct_info_data(current_data, type, field, id);
3622                 notify_info_data_table[j].fn(snum, current_data, queue,
3623                                              printer, mem_ctx);
3624                 info->count++;
3625         }
3626
3627         return True;
3628 }
3629
3630 /*
3631  * JFM: The enumeration is not that simple, it's even non obvious.
3632  *
3633  * let's take an example: I want to monitor the PRINTER SERVER for
3634  * the printer's name and the number of jobs currently queued.
3635  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3636  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3637  *
3638  * I have 3 printers on the back of my server.
3639  *
3640  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3641  * structures.
3642  *   Number     Data                    Id
3643  *      1       printer 1 name          1
3644  *      2       printer 1 cjob          1
3645  *      3       printer 2 name          2
3646  *      4       printer 2 cjob          2
3647  *      5       printer 3 name          3
3648  *      6       printer 3 name          3
3649  *
3650  * that's the print server case, the printer case is even worse.
3651  */
3652
3653 /*******************************************************************
3654  *
3655  * enumerate all printers on the printserver
3656  * fill a notify_info struct with info asked
3657  *
3658  ********************************************************************/
3659
3660 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, 
3661                                       SPOOL_NOTIFY_INFO *info,
3662                                       TALLOC_CTX *mem_ctx)
3663 {
3664         int snum;
3665         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3666         int n_services=lp_numservices();
3667         int i;
3668         SPOOL_NOTIFY_OPTION *option;
3669         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3670
3671         DEBUG(4,("printserver_notify_info\n"));
3672         
3673         if (!Printer)
3674                 return WERR_BADFID;
3675
3676         option=Printer->notify.option;
3677         info->version=2;
3678         info->data=NULL;
3679         info->count=0;
3680
3681         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without 
3682            sending a ffpcn() request first */
3683
3684         if ( !option )
3685                 return WERR_BADFID;
3686
3687         for (i=0; i<option->count; i++) {
3688                 option_type=&(option->ctr.type[i]);
3689                 
3690                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3691                         continue;
3692                 
3693                 for (snum=0; snum<n_services; snum++)
3694                 {
3695                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3696                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3697                 }
3698         }
3699                         
3700 #if 0                   
3701         /*
3702          * Debugging information, don't delete.
3703          */
3704
3705         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3706         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3707         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3708         
3709         for (i=0; i<info->count; i++) {
3710                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3711                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3712                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3713         }
3714 #endif
3715         
3716         return WERR_OK;
3717 }
3718
3719 /*******************************************************************
3720  *
3721  * fill a notify_info struct with info asked
3722  *
3723  ********************************************************************/
3724
3725 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3726                                   TALLOC_CTX *mem_ctx)
3727 {
3728         int snum;
3729         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3730         int i;
3731         uint32 id;
3732         SPOOL_NOTIFY_OPTION *option;
3733         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3734         int count,j;
3735         print_queue_struct *queue=NULL;
3736         print_status_struct status;
3737         
3738         DEBUG(4,("printer_notify_info\n"));
3739
3740         if (!Printer)
3741                 return WERR_BADFID;
3742
3743         option=Printer->notify.option;
3744         id = 0x0;
3745         info->version=2;
3746         info->data=NULL;
3747         info->count=0;
3748
3749         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without 
3750            sending a ffpcn() request first */
3751
3752         if ( !option )
3753                 return WERR_BADFID;
3754
3755         get_printer_snum(p, hnd, &snum);
3756
3757         for (i=0; i<option->count; i++) {
3758                 option_type=&option->ctr.type[i];
3759                 
3760                 switch ( option_type->type ) {
3761                 case PRINTER_NOTIFY_TYPE:
3762                         if(construct_notify_printer_info(Printer, info, snum, 
3763                                                          option_type, id,
3764                                                          mem_ctx))  
3765                                 id--;
3766                         break;
3767                         
3768                 case JOB_NOTIFY_TYPE: {
3769                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3770
3771                         count = print_queue_status(snum, &queue, &status);
3772
3773                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3774                                 goto done;
3775
3776                         for (j=0; j<count; j++) {
3777                                 construct_notify_jobs_info(&queue[j], info,
3778                                                            printer, snum,
3779                                                            option_type,
3780                                                            queue[j].job,
3781                                                            mem_ctx); 
3782                         }
3783
3784                         free_a_printer(&printer, 2);
3785                         
3786                 done:
3787                         SAFE_FREE(queue);
3788                         break;
3789                 }
3790                 }
3791         }
3792         
3793         /*
3794          * Debugging information, don't delete.
3795          */
3796         /*
3797         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3798         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3799         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3800         
3801         for (i=0; i<info->count; i++) {
3802                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3803                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3804                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3805         }
3806         */
3807         return WERR_OK;
3808 }
3809
3810 /********************************************************************
3811  * spoolss_rfnpcnex
3812  ********************************************************************/
3813
3814 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3815 {
3816         POLICY_HND *handle = &q_u->handle;
3817         SPOOL_NOTIFY_INFO *info = &r_u->info;
3818
3819         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3820         WERROR result = WERR_BADFID;
3821
3822         /* we always have a NOTIFY_INFO struct */
3823         r_u->info_ptr=0x1;
3824
3825         if (!Printer) {
3826                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3827                          OUR_HANDLE(handle)));
3828                 goto done;
3829         }
3830
3831         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3832
3833         /*
3834          *      We are now using the change value, and 
3835          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3836          *      I don't have a global notification system, I'm sending back all the
3837          *      informations even when _NOTHING_ has changed.
3838          */
3839
3840         /* We need to keep track of the change value to send back in 
3841            RRPCN replies otherwise our updates are ignored. */
3842
3843         Printer->notify.fnpcn = True;
3844
3845         if (Printer->notify.client_connected) {
3846                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3847                 Printer->notify.change = q_u->change;
3848         }
3849
3850         /* just ignore the SPOOL_NOTIFY_OPTION */
3851         
3852         switch (Printer->printer_type) {
3853                 case SPLHND_SERVER:
3854                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3855                         break;
3856                         
3857                 case SPLHND_PRINTER:
3858                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3859                         break;
3860         }
3861         
3862         Printer->notify.fnpcn = False;
3863         
3864 done:
3865         return result;
3866 }
3867
3868 /********************************************************************
3869  * construct_printer_info_0
3870  * fill a printer_info_0 struct
3871  ********************************************************************/
3872
3873 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3874 {
3875         pstring chaine;
3876         int count;
3877         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3878         counter_printer_0 *session_counter;
3879         uint32 global_counter;
3880         struct tm *t;
3881         time_t setuptime;
3882         print_status_struct status;
3883         
3884         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3885                 return False;
3886
3887         count = print_queue_length(snum, &status);
3888
3889         /* check if we already have a counter for this printer */       
3890         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3891                 if (session_counter->snum == snum)
3892                         break;
3893         }
3894
3895         /* it's the first time, add it to the list */
3896         if (session_counter==NULL) {
3897                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3898                         free_a_printer(&ntprinter, 2);
3899                         return False;
3900                 }
3901                 ZERO_STRUCTP(session_counter);
3902                 session_counter->snum=snum;
3903                 session_counter->counter=0;
3904                 DLIST_ADD(counter_list, session_counter);
3905         }
3906         
3907         /* increment it */
3908         session_counter->counter++;
3909         
3910         /* JFM:
3911          * the global_counter should be stored in a TDB as it's common to all the clients
3912          * and should be zeroed on samba startup
3913          */
3914         global_counter=session_counter->counter;
3915         
3916         pstrcpy(chaine,ntprinter->info_2->printername);
3917
3918         init_unistr(&printer->printername, chaine);
3919         
3920         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3921         init_unistr(&printer->servername, chaine);
3922         
3923         printer->cjobs = count;
3924         printer->total_jobs = 0;
3925         printer->total_bytes = 0;
3926
3927         setuptime = (time_t)ntprinter->info_2->setuptime;
3928         t=gmtime(&setuptime);
3929
3930         printer->year = t->tm_year+1900;
3931         printer->month = t->tm_mon+1;
3932         printer->dayofweek = t->tm_wday;
3933         printer->day = t->tm_mday;
3934         printer->hour = t->tm_hour;
3935         printer->minute = t->tm_min;
3936         printer->second = t->tm_sec;
3937         printer->milliseconds = 0;
3938
3939         printer->global_counter = global_counter;
3940         printer->total_pages = 0;
3941         
3942         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3943         printer->major_version = 0x0005;        /* NT 5 */
3944         printer->build_version = 0x0893;        /* build 2195 */
3945         
3946         printer->unknown7 = 0x1;
3947         printer->unknown8 = 0x0;
3948         printer->unknown9 = 0x0;
3949         printer->session_counter = session_counter->counter;
3950         printer->unknown11 = 0x0;
3951         printer->printer_errors = 0x0;          /* number of print failure */
3952         printer->unknown13 = 0x0;
3953         printer->unknown14 = 0x1;
3954         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3955         printer->unknown16 =  0x0;
3956         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3957         printer->unknown18 =  0x0;
3958         printer->status = nt_printq_status(status.status);
3959         printer->unknown20 =  0x0;
3960         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3961         printer->unknown22 = 0x0;
3962         printer->unknown23 = 0x6;               /* 6  ???*/
3963         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
3964         printer->unknown25 = 0;
3965         printer->unknown26 = 0;
3966         printer->unknown27 = 0;
3967         printer->unknown28 = 0;
3968         printer->unknown29 = 0;
3969         
3970         free_a_printer(&ntprinter,2);
3971         return (True);  
3972 }
3973
3974 /********************************************************************
3975  * construct_printer_info_1
3976  * fill a printer_info_1 struct
3977  ********************************************************************/
3978 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3979 {
3980         pstring chaine;
3981         pstring chaine2;
3982         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3983
3984         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3985                 return False;
3986
3987         printer->flags=flags;
3988
3989         if (*ntprinter->info_2->comment == '\0') {
3990                 init_unistr(&printer->comment, lp_comment(snum));
3991                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3992                         ntprinter->info_2->drivername, lp_comment(snum));
3993         }
3994         else {
3995                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3996                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3997                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
3998         }
3999                 
4000         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4001
4002         init_unistr(&printer->description, chaine);
4003         init_unistr(&printer->name, chaine2);   
4004         
4005         free_a_printer(&ntprinter,2);
4006
4007         return True;
4008 }
4009
4010 /****************************************************************************
4011  Free a DEVMODE struct.
4012 ****************************************************************************/
4013
4014 static void free_dev_mode(DEVICEMODE *dev)
4015 {
4016         if (dev == NULL)
4017                 return;
4018
4019         SAFE_FREE(dev->dev_private);
4020         SAFE_FREE(dev); 
4021 }
4022
4023
4024 /****************************************************************************
4025  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers 
4026  should be valid upon entry
4027 ****************************************************************************/
4028
4029 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4030 {
4031         if ( !devmode || !ntdevmode )
4032                 return False;
4033                 
4034         init_unistr(&devmode->devicename, ntdevmode->devicename);
4035
4036         init_unistr(&devmode->formname, ntdevmode->formname);
4037
4038         devmode->specversion      = ntdevmode->specversion;
4039         devmode->driverversion    = ntdevmode->driverversion;
4040         devmode->size             = ntdevmode->size;
4041         devmode->driverextra      = ntdevmode->driverextra;
4042         devmode->fields           = ntdevmode->fields;
4043                                 
4044         devmode->orientation      = ntdevmode->orientation;     
4045         devmode->papersize        = ntdevmode->papersize;
4046         devmode->paperlength      = ntdevmode->paperlength;
4047         devmode->paperwidth       = ntdevmode->paperwidth;
4048         devmode->scale            = ntdevmode->scale;
4049         devmode->copies           = ntdevmode->copies;
4050         devmode->defaultsource    = ntdevmode->defaultsource;
4051         devmode->printquality     = ntdevmode->printquality;
4052         devmode->color            = ntdevmode->color;
4053         devmode->duplex           = ntdevmode->duplex;
4054         devmode->yresolution      = ntdevmode->yresolution;
4055         devmode->ttoption         = ntdevmode->ttoption;
4056         devmode->collate          = ntdevmode->collate;
4057         devmode->icmmethod        = ntdevmode->icmmethod;
4058         devmode->icmintent        = ntdevmode->icmintent;
4059         devmode->mediatype        = ntdevmode->mediatype;
4060         devmode->dithertype       = ntdevmode->dithertype;
4061
4062         if (ntdevmode->nt_dev_private != NULL) {
4063                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4064                         return False;
4065         }
4066         
4067         return True;
4068 }
4069
4070 /****************************************************************************
4071  Create a DEVMODE struct. Returns malloced memory.
4072 ****************************************************************************/
4073
4074 DEVICEMODE *construct_dev_mode(int snum)
4075 {
4076         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4077         DEVICEMODE              *devmode = NULL;
4078         
4079         DEBUG(7,("construct_dev_mode\n"));
4080         
4081         DEBUGADD(8,("getting printer characteristics\n"));
4082
4083         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) 
4084                 return NULL;
4085
4086         if ( !printer->info_2->devmode ) {
4087                 DEBUG(5, ("BONG! There was no device mode!\n"));
4088                 goto done;
4089         }
4090
4091         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4092                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4093                 goto done;
4094         }
4095
4096         ZERO_STRUCTP(devmode);  
4097         
4098         DEBUGADD(8,("loading DEVICEMODE\n"));
4099
4100         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4101                 free_dev_mode( devmode );
4102                 devmode = NULL;
4103         }
4104
4105 done:
4106         free_a_printer(&printer,2);
4107
4108         return devmode;
4109 }
4110
4111 /********************************************************************
4112  * construct_printer_info_2
4113  * fill a printer_info_2 struct
4114  ********************************************************************/
4115
4116 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4117 {
4118         int count;
4119         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4120
4121         print_status_struct status;
4122
4123         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4124                 return False;
4125                 
4126         count = print_queue_length(snum, &status);
4127
4128         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4129         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4130         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4131         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
4132         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4133
4134         if (*ntprinter->info_2->comment == '\0')
4135                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
4136         else
4137                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4138
4139         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
4140         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4141         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4142         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
4143         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
4144
4145         printer->attributes = ntprinter->info_2->attributes;
4146
4147         printer->priority = ntprinter->info_2->priority;                                /* priority */  
4148         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4149         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4150         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4151         printer->status = nt_printq_status(status.status);                      /* status */
4152         printer->cjobs = count;                                                 /* jobs */
4153         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4154                         
4155         if ( !(printer->devmode = construct_dev_mode(snum)) )
4156                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4157
4158         printer->secdesc = NULL;
4159
4160         if ( ntprinter->info_2->secdesc_buf 
4161                 && ntprinter->info_2->secdesc_buf->len != 0 ) 
4162         {
4163                 /* don't use talloc_steal() here unless you do a deep steal of all 
4164                    the SEC_DESC members */
4165
4166                 printer->secdesc = dup_sec_desc( get_talloc_ctx(), 
4167                         ntprinter->info_2->secdesc_buf->sec );
4168         }
4169
4170         free_a_printer(&ntprinter, 2);
4171
4172         return True;
4173 }
4174
4175 /********************************************************************
4176  * construct_printer_info_3
4177  * fill a printer_info_3 struct
4178  ********************************************************************/
4179
4180 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4181 {
4182         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4183         PRINTER_INFO_3 *printer = NULL;
4184
4185         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4186                 return False;
4187
4188         *pp_printer = NULL;
4189         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4190                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4191                 return False;
4192         }
4193
4194         ZERO_STRUCTP(printer);
4195         
4196         /* These are the components of the SD we are returning. */
4197
4198         printer->flags = 0x4; 
4199
4200         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4201                 /* don't use talloc_steal() here unless you do a deep steal of all 
4202                    the SEC_DESC members */
4203
4204                 printer->secdesc = dup_sec_desc( get_talloc_ctx(), 
4205                         ntprinter->info_2->secdesc_buf->sec );
4206         }
4207
4208         free_a_printer(&ntprinter, 2);
4209
4210         *pp_printer = printer;
4211         return True;
4212 }
4213
4214 /********************************************************************
4215  * construct_printer_info_4
4216  * fill a printer_info_4 struct
4217  ********************************************************************/
4218
4219 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4220 {
4221         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4222
4223         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4224                 return False;
4225                 
4226         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4227         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4228         printer->attributes = ntprinter->info_2->attributes;
4229
4230         free_a_printer(&ntprinter, 2);
4231         return True;
4232 }
4233
4234 /********************************************************************
4235  * construct_printer_info_5
4236  * fill a printer_info_5 struct
4237  ********************************************************************/
4238
4239 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4240 {
4241         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4242
4243         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4244                 return False;
4245                 
4246         init_unistr(&printer->printername, ntprinter->info_2->printername);
4247         init_unistr(&printer->portname, ntprinter->info_2->portname); 
4248         printer->attributes = ntprinter->info_2->attributes;
4249
4250         /* these two are not used by NT+ according to MSDN */
4251
4252         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4253         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4254
4255         free_a_printer(&ntprinter, 2);
4256
4257         return True;
4258 }
4259
4260 /********************************************************************
4261  * construct_printer_info_7
4262  * fill a printer_info_7 struct
4263  ********************************************************************/
4264
4265 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4266 {
4267         char *guid_str = NULL;
4268         struct uuid guid; 
4269         
4270         if (is_printer_published(print_hnd, snum, &guid)) {
4271                 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4272                 strupper_m(guid_str);
4273                 init_unistr(&printer->guid, guid_str);
4274                 printer->action = SPOOL_DS_PUBLISH;
4275         } else {
4276                 init_unistr(&printer->guid, "");
4277                 printer->action = SPOOL_DS_UNPUBLISH;
4278         }
4279
4280         return True;
4281 }
4282
4283 /********************************************************************
4284  Spoolss_enumprinters.
4285 ********************************************************************/
4286
4287 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4288 {
4289         int snum;
4290         int i;
4291         int n_services=lp_numservices();
4292         PRINTER_INFO_1 *printers=NULL;
4293         PRINTER_INFO_1 current_prt;
4294         WERROR result = WERR_OK;
4295         
4296         DEBUG(4,("enum_all_printers_info_1\n"));        
4297
4298         for (snum=0; snum<n_services; snum++) {
4299                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4300                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4301
4302                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4303                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4304                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4305                                         *returned=0;
4306                                         return WERR_NOMEM;
4307                                 }
4308                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
4309
4310                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4311                                 (*returned)++;
4312                         }
4313                 }
4314         }
4315                 
4316         /* check the required size. */  
4317         for (i=0; i<*returned; i++)
4318                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4319
4320         if (*needed > offered) {
4321                 result = WERR_INSUFFICIENT_BUFFER;
4322                 goto out;
4323         }
4324
4325         if (!rpcbuf_alloc_size(buffer, *needed)) {
4326                 result = WERR_NOMEM;
4327                 goto out;
4328         }
4329
4330         /* fill the buffer with the structures */
4331         for (i=0; i<*returned; i++)
4332                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
4333
4334 out:
4335         /* clear memory */
4336
4337         SAFE_FREE(printers);
4338
4339         if ( !W_ERROR_IS_OK(result) )
4340                 *returned = 0;
4341
4342         return result;
4343 }
4344
4345 /********************************************************************
4346  enum_all_printers_info_1_local.
4347 *********************************************************************/
4348
4349 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4350 {
4351         DEBUG(4,("enum_all_printers_info_1_local\n"));  
4352         
4353         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4354 }
4355
4356 /********************************************************************
4357  enum_all_printers_info_1_name.
4358 *********************************************************************/
4359
4360 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4361 {
4362         char *s = name;
4363         
4364         DEBUG(4,("enum_all_printers_info_1_name\n"));   
4365         
4366         if ((name[0] == '\\') && (name[1] == '\\'))
4367                 s = name + 2;
4368                 
4369         if (is_myname_or_ipaddr(s)) {
4370                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4371         }
4372         else
4373                 return WERR_INVALID_NAME;
4374 }
4375
4376 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4377 /********************************************************************
4378  enum_all_printers_info_1_remote.
4379 *********************************************************************/
4380
4381 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4382 {
4383         PRINTER_INFO_1 *printer;
4384         fstring printername;
4385         fstring desc;
4386         fstring comment;
4387         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
4388         WERROR result = WERR_OK;
4389
4390         /* JFM: currently it's more a place holder than anything else.
4391          * In the spooler world there is a notion of server registration.
4392          * the print servers are registered on the PDC (in the same domain)
4393          *
4394          * We should have a TDB here. The registration is done thru an 
4395          * undocumented RPC call.
4396          */
4397         
4398         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4399                 return WERR_NOMEM;
4400
4401         *returned=1;
4402         
4403         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);                
4404         slprintf(desc, sizeof(desc)-1,"%s", name);
4405         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4406
4407         init_unistr(&printer->description, desc);
4408         init_unistr(&printer->name, printername);       
4409         init_unistr(&printer->comment, comment);
4410         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4411                 
4412         /* check the required size. */  
4413         *needed += spoolss_size_printer_info_1(printer);
4414
4415         if (*needed > offered) {
4416                 result = WERR_INSUFFICIENT_BUFFER;
4417                 goto out;
4418         }
4419
4420         if (!rpcbuf_alloc_size(buffer, *needed)) {
4421                 result = WERR_NOMEM;
4422                 goto out;
4423         }
4424
4425         /* fill the buffer with the structures */
4426         smb_io_printer_info_1("", buffer, printer, 0);  
4427
4428 out:
4429         /* clear memory */
4430         SAFE_FREE(printer);
4431
4432         if ( !W_ERROR_IS_OK(result) )
4433                 *returned = 0;
4434
4435         return result;
4436 }
4437
4438 #endif
4439
4440 /********************************************************************
4441  enum_all_printers_info_1_network.
4442 *********************************************************************/
4443
4444 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4445 {
4446         char *s = name;
4447
4448         DEBUG(4,("enum_all_printers_info_1_network\n"));        
4449         
4450         /* If we respond to a enum_printers level 1 on our name with flags
4451            set to PRINTER_ENUM_REMOTE with a list of printers then these
4452            printers incorrectly appear in the APW browse list.
4453            Specifically the printers for the server appear at the workgroup
4454            level where all the other servers in the domain are
4455            listed. Windows responds to this call with a
4456            WERR_CAN_NOT_COMPLETE so we should do the same. */ 
4457
4458         if (name[0] == '\\' && name[1] == '\\')
4459                  s = name + 2;
4460
4461         if (is_myname_or_ipaddr(s))
4462                  return WERR_CAN_NOT_COMPLETE;
4463
4464         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4465 }
4466
4467 /********************************************************************
4468  * api_spoolss_enumprinters
4469  *
4470  * called from api_spoolss_enumprinters (see this to understand)
4471  ********************************************************************/
4472
4473 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4474 {
4475         int snum;
4476         int i;
4477         int n_services=lp_numservices();
4478         PRINTER_INFO_2 *printers=NULL;
4479         PRINTER_INFO_2 current_prt;
4480         WERROR result = WERR_OK;
4481
4482         *returned = 0;
4483
4484         for (snum=0; snum<n_services; snum++) {
4485                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4486                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4487                                 
4488                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4489                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4490                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4491                                         *returned = 0;
4492                                         return WERR_NOMEM;
4493                                 }
4494
4495                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));         
4496
4497                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4498
4499                                 (*returned)++;
4500                         }
4501                 }
4502         }
4503         
4504         /* check the required size. */  
4505         for (i=0; i<*returned; i++) 
4506                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4507         
4508         if (*needed > offered) {
4509                 result = WERR_INSUFFICIENT_BUFFER;
4510                 goto out;
4511         }
4512
4513         if (!rpcbuf_alloc_size(buffer, *needed)) {
4514                 result = WERR_NOMEM;
4515                 goto out;
4516         }
4517
4518         /* fill the buffer with the structures */
4519         for (i=0; i<*returned; i++)
4520                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
4521         
4522 out:
4523         /* clear memory */
4524
4525         for (i=0; i<*returned; i++) 
4526                 free_devmode(printers[i].devmode);
4527
4528         SAFE_FREE(printers);
4529
4530         if ( !W_ERROR_IS_OK(result) )
4531                 *returned = 0;
4532
4533         return result;
4534 }
4535
4536 /********************************************************************
4537  * handle enumeration of printers at level 1
4538  ********************************************************************/
4539
4540 static WERROR enumprinters_level1( uint32 flags, fstring name,
4541                                  RPC_BUFFER *buffer, uint32 offered,
4542                                  uint32 *needed, uint32 *returned)
4543 {
4544         /* Not all the flags are equals */
4545
4546         if (flags & PRINTER_ENUM_LOCAL)
4547                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4548
4549         if (flags & PRINTER_ENUM_NAME)
4550                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4551
4552 #if 0   /* JERRY - disabled for now */
4553         if (flags & PRINTER_ENUM_REMOTE)
4554                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4555 #endif
4556
4557         if (flags & PRINTER_ENUM_NETWORK)
4558                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4559
4560         return WERR_OK; /* NT4sp5 does that */
4561 }
4562
4563 /********************************************************************
4564  * handle enumeration of printers at level 2
4565  ********************************************************************/
4566
4567 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4568                                  RPC_BUFFER *buffer, uint32 offered,
4569                                  uint32 *needed, uint32 *returned)
4570 {
4571         char *s = servername;
4572
4573         if (flags & PRINTER_ENUM_LOCAL) {
4574                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4575         }
4576
4577         if (flags & PRINTER_ENUM_NAME) {
4578                 if ((servername[0] == '\\') && (servername[1] == '\\'))
4579                         s = servername + 2;
4580                 if (is_myname_or_ipaddr(s))
4581                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4582                 else
4583                         return WERR_INVALID_NAME;
4584         }
4585
4586         if (flags & PRINTER_ENUM_REMOTE)
4587                 return WERR_UNKNOWN_LEVEL;
4588
4589         return WERR_OK;
4590 }
4591
4592 /********************************************************************
4593  * handle enumeration of printers at level 5
4594  ********************************************************************/
4595
4596 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4597                                  RPC_BUFFER *buffer, uint32 offered,
4598                                  uint32 *needed, uint32 *returned)
4599 {
4600 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4601         return WERR_OK;
4602 }
4603
4604 /********************************************************************
4605  * api_spoolss_enumprinters
4606  *
4607  * called from api_spoolss_enumprinters (see this to understand)
4608  ********************************************************************/
4609
4610 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4611 {
4612         uint32 flags = q_u->flags;
4613         UNISTR2 *servername = &q_u->servername;
4614         uint32 level = q_u->level;
4615         RPC_BUFFER *buffer = NULL;
4616         uint32 offered = q_u->offered;
4617         uint32 *needed = &r_u->needed;
4618         uint32 *returned = &r_u->returned;
4619
4620         fstring name;
4621         
4622         /* that's an [in out] buffer */
4623
4624         if (!q_u->buffer && (offered!=0)) {
4625                 return WERR_INVALID_PARAM;
4626         }
4627
4628         rpcbuf_move(q_u->buffer, &r_u->buffer);
4629         buffer = r_u->buffer;
4630
4631         DEBUG(4,("_spoolss_enumprinters\n"));
4632
4633         *needed=0;
4634         *returned=0;
4635         
4636         /*
4637          * Level 1:
4638          *          flags==PRINTER_ENUM_NAME
4639          *           if name=="" then enumerates all printers
4640          *           if name!="" then enumerate the printer
4641          *          flags==PRINTER_ENUM_REMOTE
4642          *          name is NULL, enumerate printers
4643          * Level 2: name!="" enumerates printers, name can't be NULL
4644          * Level 3: doesn't exist
4645          * Level 4: does a local registry lookup
4646          * Level 5: same as Level 2
4647          */
4648
4649         unistr2_to_ascii(name, servername, sizeof(name)-1);
4650         strupper_m(name);
4651
4652         switch (level) {
4653         case 1:
4654                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4655         case 2:
4656                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4657         case 5:
4658                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4659         case 3:
4660         case 4:
4661                 break;
4662         }
4663         return WERR_UNKNOWN_LEVEL;
4664 }
4665
4666 /****************************************************************************
4667 ****************************************************************************/
4668
4669 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4670 {
4671         PRINTER_INFO_0 *printer=NULL;
4672         WERROR result = WERR_OK;
4673
4674         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4675                 return WERR_NOMEM;
4676
4677         construct_printer_info_0(print_hnd, printer, snum);
4678         
4679         /* check the required size. */  
4680         *needed += spoolss_size_printer_info_0(printer);
4681
4682         if (*needed > offered) {
4683                 result = WERR_INSUFFICIENT_BUFFER;
4684                 goto out;
4685         }
4686
4687         if (!rpcbuf_alloc_size(buffer, *needed)) {
4688                 result = WERR_NOMEM;
4689                 goto out;
4690         }
4691
4692         /* fill the buffer with the structures */
4693         smb_io_printer_info_0("", buffer, printer, 0);  
4694         
4695 out:
4696         /* clear memory */
4697
4698         SAFE_FREE(printer);
4699
4700         return result;
4701 }
4702
4703 /****************************************************************************
4704 ****************************************************************************/
4705
4706 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4707 {
4708         PRINTER_INFO_1 *printer=NULL;
4709         WERROR result = WERR_OK;
4710
4711         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4712                 return WERR_NOMEM;
4713
4714         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4715         
4716         /* check the required size. */  
4717         *needed += spoolss_size_printer_info_1(printer);
4718
4719         if (*needed > offered) {
4720                 result = WERR_INSUFFICIENT_BUFFER;
4721                 goto out;
4722         }
4723
4724         if (!rpcbuf_alloc_size(buffer, *needed)) {
4725                 result = WERR_NOMEM;
4726                 goto out;
4727         }
4728
4729         /* fill the buffer with the structures */
4730         smb_io_printer_info_1("", buffer, printer, 0);  
4731         
4732 out:
4733         /* clear memory */
4734         SAFE_FREE(printer);
4735
4736         return result;  
4737 }
4738
4739 /****************************************************************************
4740 ****************************************************************************/
4741
4742 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4743 {
4744         PRINTER_INFO_2 *printer=NULL;
4745         WERROR result = WERR_OK;
4746
4747         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4748                 return WERR_NOMEM;
4749         
4750         construct_printer_info_2(print_hnd, printer, snum);
4751         
4752         /* check the required size. */  
4753         *needed += spoolss_size_printer_info_2(printer);
4754         
4755         if (*needed > offered) {
4756                 result = WERR_INSUFFICIENT_BUFFER;
4757                 goto out;
4758         }
4759
4760         if (!rpcbuf_alloc_size(buffer, *needed)) {
4761                 result = WERR_NOMEM;
4762                 goto out;
4763         }
4764
4765         /* fill the buffer with the structures */
4766         if (!smb_io_printer_info_2("", buffer, printer, 0)) 
4767                 result = WERR_NOMEM;
4768         
4769 out:
4770         /* clear memory */
4771         free_printer_info_2(printer);
4772
4773         return result;  
4774 }
4775
4776 /****************************************************************************
4777 ****************************************************************************/
4778
4779 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4780 {
4781         PRINTER_INFO_3 *printer=NULL;
4782         WERROR result = WERR_OK;
4783
4784         if (!construct_printer_info_3(print_hnd, &printer, snum))
4785                 return WERR_NOMEM;
4786         
4787         /* check the required size. */  
4788         *needed += spoolss_size_printer_info_3(printer);
4789
4790         if (*needed > offered) {
4791                 result = WERR_INSUFFICIENT_BUFFER;
4792                 goto out;
4793         }
4794
4795         if (!rpcbuf_alloc_size(buffer, *needed)) {
4796                 result = WERR_NOMEM;
4797                 goto out;
4798         }
4799
4800         /* fill the buffer with the structures */
4801         smb_io_printer_info_3("", buffer, printer, 0);  
4802         
4803 out:
4804         /* clear memory */
4805         free_printer_info_3(printer);
4806         
4807         return result;  
4808 }
4809
4810 /****************************************************************************
4811 ****************************************************************************/
4812
4813 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4814 {
4815         PRINTER_INFO_4 *printer=NULL;
4816         WERROR result = WERR_OK;
4817
4818         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4819                 return WERR_NOMEM;
4820
4821         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4822                 SAFE_FREE(printer);
4823                 return WERR_NOMEM;
4824         }
4825         
4826         /* check the required size. */  
4827         *needed += spoolss_size_printer_info_4(printer);
4828
4829         if (*needed > offered) {
4830                 result = WERR_INSUFFICIENT_BUFFER;
4831                 goto out;
4832         }
4833
4834         if (!rpcbuf_alloc_size(buffer, *needed)) {
4835                 result = WERR_NOMEM;
4836                 goto out;
4837         }
4838
4839         /* fill the buffer with the structures */
4840         smb_io_printer_info_4("", buffer, printer, 0);  
4841         
4842 out:
4843         /* clear memory */
4844         free_printer_info_4(printer);
4845         
4846         return result;  
4847 }
4848
4849 /****************************************************************************
4850 ****************************************************************************/
4851
4852 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4853 {
4854         PRINTER_INFO_5 *printer=NULL;
4855         WERROR result = WERR_OK;
4856
4857         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4858                 return WERR_NOMEM;
4859
4860         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4861                 free_printer_info_5(printer);
4862                 return WERR_NOMEM;
4863         }
4864         
4865         /* check the required size. */  
4866         *needed += spoolss_size_printer_info_5(printer);
4867
4868         if (*needed > offered) {
4869                 result = WERR_INSUFFICIENT_BUFFER;
4870                 goto out;
4871         }
4872
4873         if (!rpcbuf_alloc_size(buffer, *needed)) {
4874                 result = WERR_NOMEM;
4875                 goto out;
4876         }
4877
4878         /* fill the buffer with the structures */
4879         smb_io_printer_info_5("", buffer, printer, 0);  
4880         
4881 out:
4882         /* clear memory */
4883         free_printer_info_5(printer);
4884         
4885         return result;  
4886 }
4887
4888 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 {
4890         PRINTER_INFO_7 *printer=NULL;
4891         WERROR result = WERR_OK;
4892
4893         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4894                 return WERR_NOMEM;
4895
4896         if (!construct_printer_info_7(print_hnd, printer, snum))
4897                 return WERR_NOMEM;
4898         
4899         /* check the required size. */  
4900         *needed += spoolss_size_printer_info_7(printer);
4901
4902         if (*needed > offered) {
4903                 result = WERR_INSUFFICIENT_BUFFER;
4904                 goto out;
4905         }
4906
4907         if (!rpcbuf_alloc_size(buffer, *needed)) {
4908                 result = WERR_NOMEM;
4909                 goto out;
4910
4911         }
4912
4913         /* fill the buffer with the structures */
4914         smb_io_printer_info_7("", buffer, printer, 0);  
4915         
4916 out:
4917         /* clear memory */
4918         free_printer_info_7(printer);
4919         
4920         return result;  
4921 }
4922
4923 /****************************************************************************
4924 ****************************************************************************/
4925
4926 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4927 {
4928         POLICY_HND *handle = &q_u->handle;
4929         uint32 level = q_u->level;
4930         RPC_BUFFER *buffer = NULL;
4931         uint32 offered = q_u->offered;
4932         uint32 *needed = &r_u->needed;
4933         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4934
4935         int snum;
4936
4937         /* that's an [in out] buffer */
4938
4939         if (!q_u->buffer && (offered!=0)) {
4940                 return WERR_INVALID_PARAM;
4941         }
4942
4943         rpcbuf_move(q_u->buffer, &r_u->buffer);
4944         buffer = r_u->buffer;
4945
4946         *needed=0;
4947
4948         if (!get_printer_snum(p, handle, &snum))
4949                 return WERR_BADFID;
4950
4951         switch (level) {
4952         case 0:
4953                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4954         case 1:
4955                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4956         case 2:         
4957                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4958         case 3:         
4959                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4960         case 4:         
4961                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4962         case 5:         
4963                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4964         case 7:
4965                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4966         }
4967         return WERR_UNKNOWN_LEVEL;
4968 }       
4969                 
4970 /********************************************************************
4971  * fill a DRIVER_INFO_1 struct
4972  ********************************************************************/
4973
4974 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4975 {
4976         init_unistr( &info->name, driver.info_3->name);
4977 }
4978
4979 /********************************************************************
4980  * construct_printer_driver_info_1
4981  ********************************************************************/
4982
4983 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4984 {       
4985         NT_PRINTER_INFO_LEVEL *printer = NULL;
4986         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4987
4988         ZERO_STRUCT(driver);
4989
4990         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4991                 return WERR_INVALID_PRINTER_NAME;
4992
4993         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4994                 return WERR_UNKNOWN_PRINTER_DRIVER;
4995
4996         fill_printer_driver_info_1(info, driver, servername, architecture);
4997
4998         free_a_printer(&printer,2);
4999
5000         return WERR_OK;
5001 }
5002
5003 /********************************************************************
5004  * construct_printer_driver_info_2
5005  * fill a printer_info_2 struct
5006  ********************************************************************/
5007
5008 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5009 {
5010         pstring temp;
5011
5012         info->version=driver.info_3->cversion;
5013
5014         init_unistr( &info->name, driver.info_3->name );
5015         init_unistr( &info->architecture, driver.info_3->environment );
5016
5017
5018     if (strlen(driver.info_3->driverpath)) {
5019                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5020                 init_unistr( &info->driverpath, temp );
5021     } else
5022         init_unistr( &info->driverpath, "" );
5023
5024         if (strlen(driver.info_3->datafile)) {
5025                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5026                 init_unistr( &info->datafile, temp );
5027         } else
5028                 init_unistr( &info->datafile, "" );
5029         
5030         if (strlen(driver.info_3->configfile)) {
5031                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5032                 init_unistr( &info->configfile, temp ); 
5033         } else
5034                 init_unistr( &info->configfile, "" );
5035 }
5036
5037 /********************************************************************
5038  * construct_printer_driver_info_2
5039  * fill a printer_info_2 struct
5040  ********************************************************************/
5041
5042 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5043 {
5044         NT_PRINTER_INFO_LEVEL *printer = NULL;
5045         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5046
5047         ZERO_STRUCT(printer);
5048         ZERO_STRUCT(driver);
5049
5050         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5051                 return WERR_INVALID_PRINTER_NAME;
5052
5053         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5054                 return WERR_UNKNOWN_PRINTER_DRIVER;
5055
5056         fill_printer_driver_info_2(info, driver, servername);
5057
5058         free_a_printer(&printer,2);
5059
5060         return WERR_OK;
5061 }
5062
5063 /********************************************************************
5064  * copy a strings array and convert to UNICODE
5065  *
5066  * convert an array of ascii string to a UNICODE string
5067  ********************************************************************/
5068
5069 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5070 {
5071         int i=0;
5072         int j=0;
5073         const char *v;
5074         pstring line;
5075
5076         DEBUG(6,("init_unistr_array\n"));
5077         *uni_array=NULL;
5078
5079         while (True) 
5080         {
5081                 if ( !char_array )
5082                         v = "";
5083                 else 
5084                 {
5085                         v = char_array[i];
5086                         if (!v) 
5087                                 v = ""; /* hack to handle null lists */
5088                 }
5089                 
5090                 /* hack to allow this to be used in places other than when generating 
5091                    the list of dependent files */
5092                    
5093                 if ( servername )
5094                         slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5095                 else
5096                         pstrcpy( line, v );
5097                         
5098                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5099
5100                 /* add one extra unit16 for the second terminating NULL */
5101                 
5102                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5103                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5104                         return 0;
5105                 }
5106
5107                 if ( !strlen(v) ) 
5108                         break;
5109                 
5110                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5111                 i++;
5112         }
5113         
5114         if (*uni_array) {
5115                 /* special case for ""; we need to add both NULL's here */
5116                 if (!j)
5117                         (*uni_array)[j++]=0x0000;       
5118                 (*uni_array)[j]=0x0000;
5119         }
5120         
5121         DEBUGADD(6,("last one:done\n"));
5122
5123         /* return size of array in uint16's */
5124                 
5125         return j+1;
5126 }
5127
5128 /********************************************************************
5129  * construct_printer_info_3
5130  * fill a printer_info_3 struct
5131  ********************************************************************/
5132
5133 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5134 {
5135         pstring temp;
5136
5137         ZERO_STRUCTP(info);
5138
5139         info->version=driver.info_3->cversion;
5140
5141         init_unistr( &info->name, driver.info_3->name );        
5142         init_unistr( &info->architecture, driver.info_3->environment );
5143
5144         if (strlen(driver.info_3->driverpath)) {
5145                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5146                 init_unistr( &info->driverpath, temp );
5147         } else
5148                 init_unistr( &info->driverpath, "" );
5149     
5150         if (strlen(driver.info_3->datafile)) {
5151                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5152                 init_unistr( &info->datafile, temp );
5153         } else
5154                 init_unistr( &info->datafile, "" );
5155
5156         if (strlen(driver.info_3->configfile)) {
5157                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5158                 init_unistr( &info->configfile, temp ); 
5159         } else
5160                 init_unistr( &info->configfile, "" );
5161
5162         if (strlen(driver.info_3->helpfile)) {
5163                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5164                 init_unistr( &info->helpfile, temp );
5165         } else
5166                 init_unistr( &info->helpfile, "" );
5167
5168         init_unistr( &info->monitorname, driver.info_3->monitorname );
5169         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5170
5171         info->dependentfiles=NULL;
5172         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5173 }
5174
5175 /********************************************************************
5176  * construct_printer_info_3
5177  * fill a printer_info_3 struct
5178  ********************************************************************/
5179
5180 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5181 {       
5182         NT_PRINTER_INFO_LEVEL *printer = NULL;
5183         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5184         WERROR status;
5185         ZERO_STRUCT(driver);
5186
5187         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5188         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5189         if (!W_ERROR_IS_OK(status))
5190                 return WERR_INVALID_PRINTER_NAME;
5191
5192         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5193         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5194
5195 #if 0   /* JERRY */
5196
5197         /* 
5198          * I put this code in during testing.  Helpful when commenting out the 
5199          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5200          * as win2k always queries the driver using an infor level of 6.
5201          * I've left it in (but ifdef'd out) because I'll probably
5202          * use it in experimentation again in the future.   --jerry 22/01/2002
5203          */
5204
5205         if (!W_ERROR_IS_OK(status)) {
5206                 /*
5207                  * Is this a W2k client ?
5208                  */
5209                 if (version == 3) {
5210                         /* Yes - try again with a WinNT driver. */
5211                         version = 2;
5212                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5213                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5214                 }
5215 #endif
5216
5217                 if (!W_ERROR_IS_OK(status)) {
5218                         free_a_printer(&printer,2);
5219                         return WERR_UNKNOWN_PRINTER_DRIVER;
5220                 }
5221                 
5222 #if 0   /* JERRY */
5223         }
5224 #endif
5225         
5226
5227         fill_printer_driver_info_3(info, driver, servername);
5228
5229         free_a_printer(&printer,2);
5230
5231         return WERR_OK;
5232 }
5233
5234 /********************************************************************
5235  * construct_printer_info_6
5236  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5237  ********************************************************************/
5238
5239 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5240 {
5241         pstring temp;
5242         fstring nullstr;
5243
5244         ZERO_STRUCTP(info);
5245         memset(&nullstr, '\0', sizeof(fstring));
5246
5247         info->version=driver.info_3->cversion;
5248
5249         init_unistr( &info->name, driver.info_3->name );        
5250         init_unistr( &info->architecture, driver.info_3->environment );
5251
5252         if (strlen(driver.info_3->driverpath)) {
5253                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5254                 init_unistr( &info->driverpath, temp );
5255         } else
5256                 init_unistr( &info->driverpath, "" );
5257
5258         if (strlen(driver.info_3->datafile)) {
5259                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5260                 init_unistr( &info->datafile, temp );
5261         } else
5262                 init_unistr( &info->datafile, "" );
5263
5264         if (strlen(driver.info_3->configfile)) {
5265                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5266                 init_unistr( &info->configfile, temp ); 
5267         } else
5268                 init_unistr( &info->configfile, "" );
5269
5270         if (strlen(driver.info_3->helpfile)) {
5271                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5272                 init_unistr( &info->helpfile, temp );
5273         } else
5274                 init_unistr( &info->helpfile, "" );
5275         
5276         init_unistr( &info->monitorname, driver.info_3->monitorname );
5277         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5278
5279         info->dependentfiles = NULL;
5280         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5281
5282         info->previousdrivernames=NULL;
5283         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5284
5285         info->driver_date.low=0;
5286         info->driver_date.high=0;
5287
5288         info->padding=0;
5289         info->driver_version_low=0;
5290         info->driver_version_high=0;
5291
5292         init_unistr( &info->mfgname, "");
5293         init_unistr( &info->oem_url, "");
5294         init_unistr( &info->hardware_id, "");
5295         init_unistr( &info->provider, "");
5296 }
5297
5298 /********************************************************************
5299  * construct_printer_info_6
5300  * fill a printer_info_6 struct
5301  ********************************************************************/
5302
5303 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, 
5304               fstring servername, fstring architecture, uint32 version)
5305 {       
5306         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5307         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5308         WERROR                          status;
5309         
5310         ZERO_STRUCT(driver);
5311
5312         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5313         
5314         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5315         
5316         if (!W_ERROR_IS_OK(status))
5317                 return WERR_INVALID_PRINTER_NAME;
5318
5319         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5320                 
5321         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5322         
5323         if (!W_ERROR_IS_OK(status)) 
5324         {
5325                 /*
5326                  * Is this a W2k client ?
5327                  */
5328
5329                 if (version < 3) {
5330                         free_a_printer(&printer,2);
5331                         return WERR_UNKNOWN_PRINTER_DRIVER;
5332                 }
5333
5334                 /* Yes - try again with a WinNT driver. */
5335                 version = 2;
5336                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5337                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338                 if (!W_ERROR_IS_OK(status)) {
5339                         free_a_printer(&printer,2);
5340                         return WERR_UNKNOWN_PRINTER_DRIVER;
5341                 }
5342         }
5343
5344         fill_printer_driver_info_6(info, driver, servername);
5345
5346         free_a_printer(&printer,2);
5347         free_a_printer_driver(driver, 3);
5348
5349         return WERR_OK;
5350 }
5351
5352 /****************************************************************************
5353 ****************************************************************************/
5354
5355 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5356 {
5357         SAFE_FREE(info->dependentfiles);
5358 }
5359
5360 /****************************************************************************
5361 ****************************************************************************/
5362
5363 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5364 {
5365         SAFE_FREE(info->dependentfiles);
5366 }
5367
5368 /****************************************************************************
5369 ****************************************************************************/
5370
5371 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5372 {
5373         DRIVER_INFO_1 *info=NULL;
5374         WERROR result;
5375         
5376         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5377                 return WERR_NOMEM;
5378         
5379         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5380         if (!W_ERROR_IS_OK(result)) 
5381                 goto out;
5382
5383         /* check the required size. */  
5384         *needed += spoolss_size_printer_driver_info_1(info);
5385
5386         if (*needed > offered) {
5387                 result = WERR_INSUFFICIENT_BUFFER;
5388                 goto out;
5389         }
5390
5391         if (!rpcbuf_alloc_size(buffer, *needed)) {
5392                 result = WERR_NOMEM;
5393                 goto out;
5394         }
5395
5396         /* fill the buffer with the structures */
5397         smb_io_printer_driver_info_1("", buffer, info, 0);      
5398
5399 out:
5400         /* clear memory */
5401         SAFE_FREE(info);
5402
5403         return result;
5404 }
5405
5406 /****************************************************************************
5407 ****************************************************************************/
5408
5409 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5410 {
5411         DRIVER_INFO_2 *info=NULL;
5412         WERROR result;
5413         
5414         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5415                 return WERR_NOMEM;
5416         
5417         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5418         if (!W_ERROR_IS_OK(result)) 
5419                 goto out;
5420
5421         /* check the required size. */  
5422         *needed += spoolss_size_printer_driver_info_2(info);
5423
5424         if (*needed > offered) {
5425                 result = WERR_INSUFFICIENT_BUFFER;
5426                 goto out;
5427         }
5428         
5429         if (!rpcbuf_alloc_size(buffer, *needed)) {
5430                 result = WERR_NOMEM;
5431                 goto out;
5432         }
5433
5434         /* fill the buffer with the structures */
5435         smb_io_printer_driver_info_2("", buffer, info, 0);      
5436
5437 out:
5438         /* clear memory */
5439         SAFE_FREE(info);
5440
5441         return result;
5442 }
5443
5444 /****************************************************************************
5445 ****************************************************************************/
5446
5447 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5448 {
5449         DRIVER_INFO_3 info;
5450         WERROR result;
5451
5452         ZERO_STRUCT(info);
5453
5454         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5455         if (!W_ERROR_IS_OK(result))
5456                 goto out;
5457
5458         /* check the required size. */  
5459         *needed += spoolss_size_printer_driver_info_3(&info);
5460
5461         if (*needed > offered) {
5462                 result = WERR_INSUFFICIENT_BUFFER;
5463                 goto out;
5464         }
5465
5466         if (!rpcbuf_alloc_size(buffer, *needed)) {
5467                 result = WERR_NOMEM;
5468                 goto out;
5469         }
5470
5471         /* fill the buffer with the structures */
5472         smb_io_printer_driver_info_3("", buffer, &info, 0);
5473
5474 out:
5475         free_printer_driver_info_3(&info);
5476
5477         return result;
5478 }
5479
5480 /****************************************************************************
5481 ****************************************************************************/
5482
5483 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5484 {
5485         DRIVER_INFO_6 info;
5486         WERROR result;
5487
5488         ZERO_STRUCT(info);
5489
5490         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5491         if (!W_ERROR_IS_OK(result)) 
5492                 goto out;
5493
5494         /* check the required size. */  
5495         *needed += spoolss_size_printer_driver_info_6(&info);
5496
5497         if (*needed > offered) {
5498                 result = WERR_INSUFFICIENT_BUFFER;
5499                 goto out;
5500         }
5501         
5502         if (!rpcbuf_alloc_size(buffer, *needed)) {
5503                 result = WERR_NOMEM;
5504                 goto out;
5505         }
5506
5507         /* fill the buffer with the structures */
5508         smb_io_printer_driver_info_6("", buffer, &info, 0);
5509
5510 out:
5511         free_printer_driver_info_6(&info);
5512
5513         return result;
5514 }
5515
5516 /****************************************************************************
5517 ****************************************************************************/
5518
5519 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5520 {
5521         POLICY_HND *handle = &q_u->handle;
5522         UNISTR2 *uni_arch = &q_u->architecture;
5523         uint32 level = q_u->level;
5524         uint32 clientmajorversion = q_u->clientmajorversion;
5525         RPC_BUFFER *buffer = NULL;
5526         uint32 offered = q_u->offered;
5527         uint32 *needed = &r_u->needed;
5528         uint32 *servermajorversion = &r_u->servermajorversion;
5529         uint32 *serverminorversion = &r_u->serverminorversion;
5530         Printer_entry *printer;
5531
5532         fstring servername;
5533         fstring architecture;
5534         int snum;
5535
5536         /* that's an [in out] buffer */
5537
5538         if (!q_u->buffer && (offered!=0)) {
5539                 return WERR_INVALID_PARAM;
5540         }
5541
5542         rpcbuf_move(q_u->buffer, &r_u->buffer);
5543         buffer = r_u->buffer;
5544
5545         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5546
5547         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5548                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5549                 return WERR_INVALID_PRINTER_NAME;
5550         }
5551
5552         *needed = 0;
5553         *servermajorversion = 0;
5554         *serverminorversion = 0;
5555
5556         fstrcpy(servername, get_server_name( printer ));
5557         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5558
5559         if (!get_printer_snum(p, handle, &snum))
5560                 return WERR_BADFID;
5561
5562         switch (level) {
5563         case 1:
5564                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565         case 2:
5566                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5567         case 3:
5568                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5569         case 6:
5570                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5571 #if 0   /* JERRY */
5572         case 101: 
5573                 /* apparently this call is the equivalent of 
5574                    EnumPrinterDataEx() for the DsDriver key */
5575                 break;
5576 #endif
5577         }
5578
5579         return WERR_UNKNOWN_LEVEL;
5580 }
5581
5582 /****************************************************************************
5583 ****************************************************************************/
5584
5585 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5586 {
5587         POLICY_HND *handle = &q_u->handle;
5588
5589         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5590
5591         if (!Printer) {
5592                 DEBUG(3,("Error in startpageprinter printer handle\n"));
5593                 return WERR_BADFID;
5594         }
5595
5596         Printer->page_started=True;
5597         return WERR_OK;
5598 }
5599
5600 /****************************************************************************
5601 ****************************************************************************/
5602
5603 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5604 {
5605         POLICY_HND *handle = &q_u->handle;
5606         int snum;
5607
5608         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5609
5610         if (!Printer) {
5611                 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5612                 return WERR_BADFID;
5613         }
5614         
5615         if (!get_printer_snum(p, handle, &snum))
5616                 return WERR_BADFID;
5617
5618         Printer->page_started=False;
5619         print_job_endpage(snum, Printer->jobid);
5620
5621         return WERR_OK;
5622 }
5623
5624 /********************************************************************
5625  * api_spoolss_getprinter
5626  * called from the spoolss dispatcher
5627  *
5628  ********************************************************************/
5629
5630 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5631 {
5632         POLICY_HND *handle = &q_u->handle;
5633         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5634         uint32 *jobid = &r_u->jobid;
5635
5636         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5637         int snum;
5638         pstring jobname;
5639         fstring datatype;
5640         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5641         struct current_user user;
5642
5643         if (!Printer) {
5644                 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5645                 return WERR_BADFID;
5646         }
5647
5648         get_current_user(&user, p);
5649
5650         /*
5651          * a nice thing with NT is it doesn't listen to what you tell it.
5652          * when asked to send _only_ RAW datas, it tries to send datas
5653          * in EMF format.
5654          *
5655          * So I add checks like in NT Server ...
5656          */
5657         
5658         if (info_1->p_datatype != 0) {
5659                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5660                 if (strcmp(datatype, "RAW") != 0) {
5661                         (*jobid)=0;
5662                         return WERR_INVALID_DATATYPE;
5663                 }               
5664         }               
5665         
5666         /* get the share number of the printer */
5667         if (!get_printer_snum(p, handle, &snum)) {
5668                 return WERR_BADFID;
5669         }
5670
5671         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5672         
5673         Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5674
5675         /* An error occured in print_job_start() so return an appropriate
5676            NT error code. */
5677
5678         if (Printer->jobid == -1) {
5679                 return map_werror_from_unix(errno);
5680         }
5681         
5682         Printer->document_started=True;
5683         (*jobid) = Printer->jobid;
5684
5685         return WERR_OK;
5686 }
5687
5688 /********************************************************************
5689  * api_spoolss_getprinter
5690  * called from the spoolss dispatcher
5691  *
5692  ********************************************************************/
5693
5694 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5695 {
5696         POLICY_HND *handle = &q_u->handle;
5697
5698         return _spoolss_enddocprinter_internal(p, handle);
5699 }
5700
5701 /****************************************************************************
5702 ****************************************************************************/
5703
5704 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5705 {
5706         POLICY_HND *handle = &q_u->handle;
5707         uint32 buffer_size = q_u->buffer_size;
5708         uint8 *buffer = q_u->buffer;
5709         uint32 *buffer_written = &q_u->buffer_size2;
5710         int snum;
5711         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5712         
5713         if (!Printer) {
5714                 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5715                 r_u->buffer_written = q_u->buffer_size2;
5716                 return WERR_BADFID;
5717         }
5718
5719         if (!get_printer_snum(p, handle, &snum))
5720                 return WERR_BADFID;
5721
5722         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5723                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5724         if (*buffer_written == (uint32)-1) {
5725                 r_u->buffer_written = 0;
5726                 if (errno == ENOSPC)
5727                         return WERR_NO_SPOOL_SPACE;
5728                 else
5729                         return WERR_ACCESS_DENIED;
5730         }
5731
5732         r_u->buffer_written = q_u->buffer_size2;
5733
5734         return WERR_OK;
5735 }
5736
5737 /********************************************************************
5738  * api_spoolss_getprinter
5739  * called from the spoolss dispatcher
5740  *
5741  ********************************************************************/
5742
5743 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5744                               pipes_struct *p)
5745 {
5746         struct current_user user;
5747         int snum;
5748         WERROR errcode = WERR_BADFUNC;
5749         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5750
5751         get_current_user(&user, p);
5752
5753         if (!Printer) {
5754                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5755                 return WERR_BADFID;
5756         }
5757
5758         if (!get_printer_snum(p, handle, &snum))
5759                 return WERR_BADFID;
5760
5761         switch (command) {
5762         case PRINTER_CONTROL_PAUSE:
5763                 if (print_queue_pause(&user, snum, &errcode)) {
5764                         errcode = WERR_OK;
5765                 }
5766                 break;
5767         case PRINTER_CONTROL_RESUME:
5768         case PRINTER_CONTROL_UNPAUSE:
5769                 if (print_queue_resume(&user, snum, &errcode)) {
5770                         errcode = WERR_OK;
5771                 }
5772                 break;
5773         case PRINTER_CONTROL_PURGE:
5774                 if (print_queue_purge(&user, snum, &errcode)) {
5775                         errcode = WERR_OK;
5776                 }
5777                 break;
5778         default:
5779                 return WERR_UNKNOWN_LEVEL;
5780         }
5781
5782         return errcode;
5783 }
5784
5785 /********************************************************************
5786  * api_spoolss_abortprinter
5787  * From MSDN: "Deletes printer's spool file if printer is configured
5788  * for spooling"
5789  ********************************************************************/
5790
5791 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5792 {
5793         POLICY_HND      *handle = &q_u->handle;
5794         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5795         int             snum;
5796         struct          current_user user;
5797         WERROR          errcode = WERR_OK;
5798         
5799         if (!Printer) {
5800                 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5801                 return WERR_BADFID;
5802         }
5803         
5804         if (!get_printer_snum(p, handle, &snum))
5805                 return WERR_BADFID;
5806         
5807         get_current_user( &user, p );   
5808         
5809         print_job_delete( &user, snum, Printer->jobid, &errcode );      
5810         
5811         return errcode;
5812 }
5813
5814 /********************************************************************
5815  * called by spoolss_api_setprinter
5816  * when updating a printer description
5817  ********************************************************************/
5818
5819 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5820                                  const SPOOL_PRINTER_INFO_LEVEL *info,
5821                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5822 {
5823         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5824         WERROR result;
5825         int snum;
5826
5827         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5828
5829         if (!Printer || !get_printer_snum(p, handle, &snum)) {
5830                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5831                          OUR_HANDLE(handle)));
5832
5833                 result = WERR_BADFID;
5834                 goto done;
5835         }
5836         
5837         /* Check the user has permissions to change the security
5838            descriptor.  By experimentation with two NT machines, the user
5839            requires Full Access to the printer to change security
5840            information. */
5841
5842         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5843                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5844                 result = WERR_ACCESS_DENIED;
5845                 goto done;
5846         }
5847
5848         /* NT seems to like setting the security descriptor even though
5849            nothing may have actually changed. */
5850
5851         nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5852
5853         if (DEBUGLEVEL >= 10) {
5854                 SEC_ACL *the_acl;
5855                 int i;
5856
5857                 the_acl = old_secdesc_ctr->sec->dacl;
5858                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
5859                            PRINTERNAME(snum), the_acl->num_aces));
5860
5861                 for (i = 0; i < the_acl->num_aces; i++) {
5862                         fstring sid_str;
5863
5864                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5865
5866                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
5867                                   the_acl->ace[i].info.mask));
5868                 }
5869
5870                 the_acl = secdesc_ctr->sec->dacl;
5871
5872                 if (the_acl) {
5873                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5874                                    PRINTERNAME(snum), the_acl->num_aces));
5875
5876                         for (i = 0; i < the_acl->num_aces; i++) {
5877                                 fstring sid_str;
5878                                 
5879                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5880                                 
5881                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
5882                                            the_acl->ace[i].info.mask));
5883                         }
5884                 } else {
5885                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5886                 }
5887         }
5888
5889         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5890
5891         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5892                 result = WERR_OK;
5893                 goto done;
5894         }
5895
5896         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5897
5898  done:
5899
5900         return result;
5901 }
5902
5903 /********************************************************************
5904  Canonicalize printer info from a client
5905
5906  ATTN: It does not matter what we set the servername to hear 
5907  since we do the necessary work in get_a_printer() to set it to 
5908  the correct value based on what the client sent in the 
5909  _spoolss_open_printer_ex().
5910  ********************************************************************/
5911
5912 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5913 {
5914         fstring printername;
5915         const char *p;
5916         
5917         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5918                 "portname=%s drivername=%s comment=%s location=%s\n",
5919                 info->servername, info->printername, info->sharename, 
5920                 info->portname, info->drivername, info->comment, info->location));
5921
5922         /* we force some elements to "correct" values */
5923         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5924         fstrcpy(info->sharename, lp_servicename(snum));
5925         
5926         /* check to see if we allow printername != sharename */
5927
5928         if ( lp_force_printername(snum) ) {
5929                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5930                         global_myname(), info->sharename );
5931         } else {
5932
5933                 /* make sure printername is in \\server\printername format */
5934         
5935                 fstrcpy( printername, info->printername );
5936                 p = printername;
5937                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5938                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5939                                 p++;
5940                 }
5941                 
5942                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5943                          global_myname(), p );
5944         }
5945
5946         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5947         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5948         
5949         
5950         
5951         return True;
5952 }
5953
5954 /****************************************************************************
5955 ****************************************************************************/
5956
5957 WERROR add_port_hook(NT_USER_TOKEN *token, const char *portname, const char *uri )
5958 {
5959         char *cmd = lp_addport_cmd();
5960         pstring command;
5961         int ret;
5962         int fd;
5963         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5964         BOOL is_print_op = False;
5965
5966         if ( !*cmd ) {
5967                 return WERR_ACCESS_DENIED;
5968         }
5969                 
5970         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", cmd, portname, uri );
5971
5972         if ( token )
5973                 is_print_op = user_has_privileges( token, &se_printop );
5974
5975         DEBUG(10,("Running [%s]\n", command));
5976
5977         /********* BEGIN SePrintOperatorPrivilege **********/
5978
5979         if ( is_print_op )
5980                 become_root();
5981         
5982         ret = smbrun(command, &fd);
5983
5984         if ( is_print_op )
5985                 unbecome_root();
5986
5987         /********* END SePrintOperatorPrivilege **********/
5988
5989         DEBUGADD(10,("returned [%d]\n", ret));
5990
5991         if ( ret != 0 ) {
5992                 if (fd != -1)
5993                         close(fd);
5994                 return WERR_ACCESS_DENIED;
5995         }
5996         
5997         return WERR_OK;
5998 }
5999
6000 /****************************************************************************
6001 ****************************************************************************/
6002
6003 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6004 {
6005         char *cmd = lp_addprinter_cmd();
6006         char **qlines;
6007         pstring command;
6008         int numlines;
6009         int ret;
6010         int fd;
6011         fstring remote_machine = "%m";
6012         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6013         BOOL is_print_op = False;
6014
6015         standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6016         
6017         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6018                         cmd, printer->info_2->printername, printer->info_2->sharename,
6019                         printer->info_2->portname, printer->info_2->drivername,
6020                         printer->info_2->location, printer->info_2->comment, remote_machine);
6021
6022         if ( token )
6023                 is_print_op = user_has_privileges( token, &se_printop );
6024
6025         DEBUG(10,("Running [%s]\n", command));
6026
6027         /********* BEGIN SePrintOperatorPrivilege **********/
6028
6029         if ( is_print_op )
6030                 become_root();
6031         
6032         if ( (ret = smbrun(command, &fd)) == 0 ) {
6033                 /* Tell everyone we updated smb.conf. */
6034                 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6035         }
6036
6037         if ( is_print_op )
6038                 unbecome_root();
6039
6040         /********* END SePrintOperatorPrivilege **********/
6041
6042         DEBUGADD(10,("returned [%d]\n", ret));
6043
6044         if ( ret != 0 ) {
6045                 if (fd != -1)
6046                         close(fd);
6047                 return False;
6048         }
6049
6050         /* reload our services immediately */
6051         reload_services( False );
6052
6053         numlines = 0;
6054         /* Get lines and convert them back to dos-codepage */
6055         qlines = fd_lines_load(fd, &numlines, 0);
6056         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6057         close(fd);
6058
6059         /* Set the portname to what the script says the portname should be. */
6060         /* but don't require anything to be return from the script exit a good error code */
6061
6062         if (numlines) {
6063                 /* Set the portname to what the script says the portname should be. */
6064                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6065                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6066         }
6067
6068         file_lines_free(qlines);
6069         return True;
6070 }
6071
6072
6073 /********************************************************************
6074  * Called by spoolss_api_setprinter
6075  * when updating a printer description.
6076  ********************************************************************/
6077
6078 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6079                            const SPOOL_PRINTER_INFO_LEVEL *info,
6080                            DEVICEMODE *devmode)
6081 {
6082         int snum;
6083         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6084         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6085         WERROR result;
6086         UNISTR2 buffer;
6087         fstring asc_buffer;
6088
6089         DEBUG(8,("update_printer\n"));
6090
6091         result = WERR_OK;
6092
6093         if (!Printer) {
6094                 result = WERR_BADFID;
6095                 goto done;
6096         }
6097
6098         if (!get_printer_snum(p, handle, &snum)) {
6099                 result = WERR_BADFID;
6100                 goto done;
6101         }
6102
6103         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6104             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6105                 result = WERR_BADFID;
6106                 goto done;
6107         }
6108
6109         DEBUGADD(8,("Converting info_2 struct\n"));
6110
6111         /*
6112          * convert_printer_info converts the incoming
6113          * info from the client and overwrites the info
6114          * just read from the tdb in the pointer 'printer'.
6115          */
6116
6117         if (!convert_printer_info(info, printer, level)) {
6118                 result =  WERR_NOMEM;
6119                 goto done;
6120         }
6121
6122         if (devmode) {
6123                 /* we have a valid devmode
6124                    convert it and link it*/
6125
6126                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6127                 if (!convert_devicemode(printer->info_2->printername, devmode,
6128                                 &printer->info_2->devmode)) {
6129                         result =  WERR_NOMEM;
6130                         goto done;
6131                 }
6132         }
6133
6134         /* Do sanity check on the requested changes for Samba */
6135
6136         if (!check_printer_ok(printer->info_2, snum)) {
6137                 result = WERR_INVALID_PARAM;
6138                 goto done;
6139         }
6140
6141         /* FIXME!!! If the driver has changed we really should verify that 
6142            it is installed before doing much else   --jerry */
6143
6144         /* Check calling user has permission to update printer description */
6145
6146         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6147                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6148                 result = WERR_ACCESS_DENIED;
6149                 goto done;
6150         }
6151
6152         /* Call addprinter hook */
6153         /* Check changes to see if this is really needed */
6154         
6155         if ( *lp_addprinter_cmd() 
6156                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6157                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6158                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6159                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6160         {
6161                 /* add_printer_hook() will call reload_services() */
6162
6163                 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6164                         result = WERR_ACCESS_DENIED;
6165                         goto done;
6166                 }
6167         }
6168         
6169         /*
6170          * When a *new* driver is bound to a printer, the drivername is used to
6171          * lookup previously saved driver initialization info, which is then
6172          * bound to the printer, simulating what happens in the Windows arch.
6173          */
6174         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6175         {
6176                 if (!set_driver_init(printer, 2)) 
6177                 {
6178                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6179                                 printer->info_2->drivername));
6180                 }
6181                 
6182                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6183                         printer->info_2->drivername));
6184                         
6185                 notify_printer_driver(snum, printer->info_2->drivername);
6186         }
6187
6188         /* 
6189          * flag which changes actually occured.  This is a small subset of 
6190          * all the possible changes.  We also have to update things in the 
6191          * DsSpooler key.
6192          */
6193
6194         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6195                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6196                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6197                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6198
6199                 notify_printer_comment(snum, printer->info_2->comment);
6200         }
6201
6202         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6203                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6204                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6205                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6206
6207                 notify_printer_sharename(snum, printer->info_2->sharename);
6208         }
6209
6210         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6211                 char *pname;
6212                 
6213                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6214                         pname++;
6215                 else
6216                         pname = printer->info_2->printername;
6217                         
6218
6219                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6220                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6221                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6222
6223                 notify_printer_printername( snum, pname );
6224         }
6225         
6226         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6227                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6228                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6229                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6230
6231                 notify_printer_port(snum, printer->info_2->portname);
6232         }
6233
6234         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6235                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6236                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6237                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6238
6239                 notify_printer_location(snum, printer->info_2->location);
6240         }
6241         
6242         /* here we need to update some more DsSpooler keys */
6243         /* uNCName, serverName, shortServerName */
6244         
6245         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6246         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6247                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6248         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6249                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6250
6251         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6252                  global_myname(), printer->info_2->sharename );
6253         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6254         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6255                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6256
6257         /* Update printer info */
6258         result = mod_a_printer(printer, 2);
6259
6260 done:
6261         free_a_printer(&printer, 2);
6262         free_a_printer(&old_printer, 2);
6263
6264
6265         return result;
6266 }
6267
6268 /****************************************************************************
6269 ****************************************************************************/
6270 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6271                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6272 {
6273 #ifdef HAVE_ADS
6274         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6275         int snum;
6276         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6277
6278         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6279
6280         if (!Printer)
6281                 return WERR_BADFID;
6282
6283         if (!get_printer_snum(p, handle, &snum))
6284                 return WERR_BADFID;
6285         
6286         nt_printer_publish(Printer, snum, info7->action);
6287         
6288         return WERR_OK;
6289 #else
6290         return WERR_UNKNOWN_LEVEL;
6291 #endif
6292 }
6293 /****************************************************************************
6294 ****************************************************************************/
6295
6296 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6297 {
6298         POLICY_HND *handle = &q_u->handle;
6299         uint32 level = q_u->level;
6300         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6301         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6302         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6303         uint32 command = q_u->command;
6304         WERROR result;
6305
6306         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6307         
6308         if (!Printer) {
6309                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6310                 return WERR_BADFID;
6311         }
6312
6313         /* check the level */   
6314         switch (level) {
6315                 case 0:
6316                         return control_printer(handle, command, p);
6317                 case 2:
6318                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6319                         if (!W_ERROR_IS_OK(result)) 
6320                                 return result;
6321                         if (secdesc_ctr)
6322                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6323                         return result;
6324                 case 3:
6325                         return update_printer_sec(handle, level, info, p,
6326                                                   secdesc_ctr);
6327                 case 7:
6328                         return publish_or_unpublish_printer(p, handle, info);
6329                 default:
6330                         return WERR_UNKNOWN_LEVEL;
6331         }
6332 }
6333
6334 /****************************************************************************
6335 ****************************************************************************/
6336
6337 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6338 {
6339         POLICY_HND *handle = &q_u->handle;
6340         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6341         
6342         if (!Printer) {
6343                 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6344                 return WERR_BADFID;
6345         }
6346
6347         if (Printer->notify.client_connected==True) {
6348                 int snum = -1;
6349
6350                 if ( Printer->printer_type == SPLHND_SERVER)
6351                         snum = -1;
6352                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6353                                 !get_printer_snum(p, handle, &snum) )
6354                         return WERR_BADFID;
6355
6356                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6357         }
6358
6359         Printer->notify.flags=0;
6360         Printer->notify.options=0;
6361         Printer->notify.localmachine[0]='\0';
6362         Printer->notify.printerlocal=0;
6363         if (Printer->notify.option)
6364                 free_spool_notify_option(&Printer->notify.option);
6365         Printer->notify.client_connected=False;
6366
6367         return WERR_OK;
6368 }
6369
6370 /****************************************************************************
6371 ****************************************************************************/
6372
6373 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6374 {
6375         /* that's an [in out] buffer */
6376
6377         if (!q_u->buffer && (q_u->offered!=0)) {
6378                 return WERR_INVALID_PARAM;
6379         }
6380
6381         rpcbuf_move(q_u->buffer, &r_u->buffer);
6382
6383         r_u->needed = 0;
6384         return WERR_INVALID_PARAM; /* this is what a NT server
6385                                            returns for AddJob. AddJob
6386                                            must fail on non-local
6387                                            printers */
6388 }
6389
6390 /****************************************************************************
6391 ****************************************************************************/
6392
6393 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6394                             int position, int snum, 
6395                             NT_PRINTER_INFO_LEVEL *ntprinter)
6396 {
6397         struct tm *t;
6398         
6399         t=gmtime(&queue->time);
6400
6401         job_info->jobid=queue->job;     
6402         init_unistr(&job_info->printername, lp_servicename(snum));
6403         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6404         init_unistr(&job_info->username, queue->fs_user);
6405         init_unistr(&job_info->document, queue->fs_file);
6406         init_unistr(&job_info->datatype, "RAW");
6407         init_unistr(&job_info->text_status, "");
6408         job_info->status=nt_printj_status(queue->status);
6409         job_info->priority=queue->priority;
6410         job_info->position=position;
6411         job_info->totalpages=queue->page_count;
6412         job_info->pagesprinted=0;
6413
6414         make_systemtime(&job_info->submitted, t);
6415 }
6416
6417 /****************************************************************************
6418 ****************************************************************************/
6419
6420 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6421                             int position, int snum, 
6422                             NT_PRINTER_INFO_LEVEL *ntprinter,
6423                             DEVICEMODE *devmode)
6424 {
6425         struct tm *t;
6426
6427         t=gmtime(&queue->time);
6428
6429         job_info->jobid=queue->job;
6430         
6431         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6432         
6433         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6434         init_unistr(&job_info->username, queue->fs_user);
6435         init_unistr(&job_info->document, queue->fs_file);
6436         init_unistr(&job_info->notifyname, queue->fs_user);
6437         init_unistr(&job_info->datatype, "RAW");
6438         init_unistr(&job_info->printprocessor, "winprint");
6439         init_unistr(&job_info->parameters, "");
6440         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6441         init_unistr(&job_info->text_status, "");
6442         
6443 /* and here the security descriptor */
6444
6445         job_info->status=nt_printj_status(queue->status);
6446         job_info->priority=queue->priority;
6447         job_info->position=position;
6448         job_info->starttime=0;
6449         job_info->untiltime=0;
6450         job_info->totalpages=queue->page_count;
6451         job_info->size=queue->size;
6452         make_systemtime(&(job_info->submitted), t);
6453         job_info->timeelapsed=0;
6454         job_info->pagesprinted=0;
6455
6456         job_info->devmode = devmode;
6457
6458         return (True);
6459 }
6460
6461 /****************************************************************************
6462  Enumjobs at level 1.
6463 ****************************************************************************/
6464
6465 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6466                               NT_PRINTER_INFO_LEVEL *ntprinter,
6467                               RPC_BUFFER *buffer, uint32 offered,
6468                               uint32 *needed, uint32 *returned)
6469 {
6470         JOB_INFO_1 *info;
6471         int i;
6472         WERROR result = WERR_OK;
6473         
6474         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6475         if (info==NULL) {
6476                 SAFE_FREE(queue);
6477                 *returned=0;
6478                 return WERR_NOMEM;
6479         }
6480         
6481         for (i=0; i<*returned; i++)
6482                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6483
6484         SAFE_FREE(queue);
6485
6486         /* check the required size. */  
6487         for (i=0; i<*returned; i++)
6488                 (*needed) += spoolss_size_job_info_1(&info[i]);
6489
6490         if (*needed > offered) {
6491                 result = WERR_INSUFFICIENT_BUFFER;
6492                 goto out;
6493         }
6494
6495         if (!rpcbuf_alloc_size(buffer, *needed)) {
6496                 result = WERR_NOMEM;
6497                 goto out;
6498         }
6499
6500         /* fill the buffer with the structures */
6501         for (i=0; i<*returned; i++)
6502                 smb_io_job_info_1("", buffer, &info[i], 0);     
6503
6504 out:
6505         /* clear memory */
6506         SAFE_FREE(info);
6507
6508         if ( !W_ERROR_IS_OK(result) )
6509                 *returned = 0;
6510
6511         return result;
6512 }
6513
6514 /****************************************************************************
6515  Enumjobs at level 2.
6516 ****************************************************************************/
6517
6518 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6519                               NT_PRINTER_INFO_LEVEL *ntprinter,
6520                               RPC_BUFFER *buffer, uint32 offered,
6521                               uint32 *needed, uint32 *returned)
6522 {
6523         JOB_INFO_2 *info = NULL;
6524         int i;
6525         WERROR result = WERR_OK;
6526         DEVICEMODE *devmode = NULL;
6527         
6528         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6529                 *returned=0;
6530                 return WERR_NOMEM;
6531         }
6532                 
6533         /* this should not be a failure condition if the devmode is NULL */
6534         
6535         devmode = construct_dev_mode(snum);
6536
6537         for (i=0; i<*returned; i++)
6538                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6539
6540         free_a_printer(&ntprinter, 2);
6541         SAFE_FREE(queue);
6542
6543         /* check the required size. */  
6544         for (i=0; i<*returned; i++)
6545                 (*needed) += spoolss_size_job_info_2(&info[i]);
6546
6547         if (*needed > offered) {
6548                 result = WERR_INSUFFICIENT_BUFFER;
6549                 goto out;
6550         }
6551
6552         if (!rpcbuf_alloc_size(buffer, *needed)) {
6553                 result = WERR_NOMEM;
6554                 goto out;
6555         }
6556
6557         /* fill the buffer with the structures */
6558         for (i=0; i<*returned; i++)
6559                 smb_io_job_info_2("", buffer, &info[i], 0);     
6560
6561 out:
6562         free_devmode(devmode);
6563         SAFE_FREE(info);
6564
6565         if ( !W_ERROR_IS_OK(result) )
6566                 *returned = 0;
6567
6568         return result;
6569
6570 }
6571
6572 /****************************************************************************
6573  Enumjobs.
6574 ****************************************************************************/
6575
6576 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6577 {       
6578         POLICY_HND *handle = &q_u->handle;
6579         uint32 level = q_u->level;
6580         RPC_BUFFER *buffer = NULL;
6581         uint32 offered = q_u->offered;
6582         uint32 *needed = &r_u->needed;
6583         uint32 *returned = &r_u->returned;
6584         WERROR wret;
6585         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6586         int snum;
6587         print_status_struct prt_status;
6588         print_queue_struct *queue=NULL;
6589
6590         /* that's an [in out] buffer */
6591
6592         if (!q_u->buffer && (offered!=0)) {
6593                 return WERR_INVALID_PARAM;
6594         }
6595
6596         rpcbuf_move(q_u->buffer, &r_u->buffer);
6597         buffer = r_u->buffer;
6598
6599         DEBUG(4,("_spoolss_enumjobs\n"));
6600
6601         *needed=0;
6602         *returned=0;
6603
6604         /* lookup the printer snum and tdb entry */
6605         
6606         if (!get_printer_snum(p, handle, &snum))
6607                 return WERR_BADFID;
6608
6609         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6610         if ( !W_ERROR_IS_OK(wret) )
6611                 return wret;
6612         
6613         *returned = print_queue_status(snum, &queue, &prt_status);
6614         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6615
6616         if (*returned == 0) {
6617                 SAFE_FREE(queue);
6618                 return WERR_OK;
6619         }
6620
6621         switch (level) {
6622         case 1:
6623                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6624                 return wret;
6625         case 2:
6626                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6627                 return wret;
6628         default:
6629                 SAFE_FREE(queue);
6630                 *returned=0;
6631                 wret = WERR_UNKNOWN_LEVEL;
6632         }
6633         
6634         free_a_printer( &ntprinter, 2 );
6635         return wret;
6636 }
6637
6638 /****************************************************************************
6639 ****************************************************************************/
6640
6641 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6642 {
6643         return WERR_OK;
6644 }
6645
6646 /****************************************************************************
6647 ****************************************************************************/
6648
6649 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6650 {
6651         POLICY_HND *handle = &q_u->handle;
6652         uint32 jobid = q_u->jobid;
6653         uint32 command = q_u->command;
6654
6655         struct current_user user;
6656         int snum;
6657         WERROR errcode = WERR_BADFUNC;
6658                 
6659         if (!get_printer_snum(p, handle, &snum)) {
6660                 return WERR_BADFID;
6661         }
6662
6663         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6664                 return WERR_INVALID_PRINTER_NAME;
6665         }
6666
6667         get_current_user(&user, p);     
6668
6669         switch (command) {
6670         case JOB_CONTROL_CANCEL:
6671         case JOB_CONTROL_DELETE:
6672                 if (print_job_delete(&user, snum, jobid, &errcode)) {
6673                         errcode = WERR_OK;
6674                 }
6675                 break;
6676         case JOB_CONTROL_PAUSE:
6677                 if (print_job_pause(&user, snum, jobid, &errcode)) {
6678                         errcode = WERR_OK;
6679                 }               
6680                 break;
6681         case JOB_CONTROL_RESTART:
6682         case JOB_CONTROL_RESUME:
6683                 if (print_job_resume(&user, snum, jobid, &errcode)) {
6684                         errcode = WERR_OK;
6685                 }
6686                 break;
6687         default:
6688                 return WERR_UNKNOWN_LEVEL;
6689         }
6690
6691         return errcode;
6692 }
6693
6694 /****************************************************************************
6695  Enumerates all printer drivers at level 1.
6696 ****************************************************************************/
6697
6698 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6699 {
6700         int i;
6701         int ndrivers;
6702         uint32 version;
6703         fstring *list = NULL;
6704         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6705         DRIVER_INFO_1 *driver_info_1=NULL;
6706         WERROR result = WERR_OK;
6707
6708         *returned=0;
6709
6710         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6711                 list=NULL;
6712                 ndrivers=get_ntdrivers(&list, architecture, version);
6713                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6714
6715                 if(ndrivers == -1) {
6716                         SAFE_FREE(driver_info_1);
6717                         return WERR_NOMEM;
6718                 }
6719
6720                 if(ndrivers != 0) {
6721                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6722                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6723                                 SAFE_FREE(list);
6724                                 return WERR_NOMEM;
6725                         }
6726                 }
6727
6728                 for (i=0; i<ndrivers; i++) {
6729                         WERROR status;
6730                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6731                         ZERO_STRUCT(driver);
6732                         status = get_a_printer_driver(&driver, 3, list[i], 
6733                                                       architecture, version);
6734                         if (!W_ERROR_IS_OK(status)) {
6735                                 SAFE_FREE(list);
6736                                 SAFE_FREE(driver_info_1);
6737                                 return status;
6738                         }
6739                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
6740                         free_a_printer_driver(driver, 3);
6741                 }       
6742
6743                 *returned+=ndrivers;
6744                 SAFE_FREE(list);
6745         }
6746         
6747         /* check the required size. */
6748         for (i=0; i<*returned; i++) {
6749                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6750                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6751         }
6752
6753         if (*needed > offered) {
6754                 result = WERR_INSUFFICIENT_BUFFER;
6755                 goto out;
6756         }
6757
6758         if (!rpcbuf_alloc_size(buffer, *needed)) {
6759                 result = WERR_NOMEM;    
6760                 goto out;
6761         }
6762
6763         /* fill the buffer with the driver structures */
6764         for (i=0; i<*returned; i++) {
6765                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6766                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6767         }
6768
6769 out:
6770         SAFE_FREE(driver_info_1);
6771
6772         if ( !W_ERROR_IS_OK(result) )
6773                 *returned = 0;
6774
6775         return result;
6776 }
6777
6778 /****************************************************************************
6779  Enumerates all printer drivers at level 2.
6780 ****************************************************************************/
6781
6782 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6783 {
6784         int i;
6785         int ndrivers;
6786         uint32 version;
6787         fstring *list = NULL;
6788         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6789         DRIVER_INFO_2 *driver_info_2=NULL;
6790         WERROR result = WERR_OK;
6791
6792         *returned=0;
6793
6794         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6795                 list=NULL;
6796                 ndrivers=get_ntdrivers(&list, architecture, version);
6797                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6798
6799                 if(ndrivers == -1) {
6800                         SAFE_FREE(driver_info_2);
6801                         return WERR_NOMEM;
6802                 }
6803
6804                 if(ndrivers != 0) {
6805                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6806                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6807                                 SAFE_FREE(list);
6808                                 return WERR_NOMEM;
6809                         }
6810                 }
6811                 
6812                 for (i=0; i<ndrivers; i++) {
6813                         WERROR status;
6814
6815                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6816                         ZERO_STRUCT(driver);
6817                         status = get_a_printer_driver(&driver, 3, list[i], 
6818                                                       architecture, version);
6819                         if (!W_ERROR_IS_OK(status)) {
6820                                 SAFE_FREE(list);
6821                                 SAFE_FREE(driver_info_2);
6822                                 return status;
6823                         }
6824                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
6825                         free_a_printer_driver(driver, 3);
6826                 }       
6827
6828                 *returned+=ndrivers;
6829                 SAFE_FREE(list);
6830         }
6831         
6832         /* check the required size. */
6833         for (i=0; i<*returned; i++) {
6834                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6835                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6836         }
6837
6838         if (*needed > offered) {
6839                 result = WERR_INSUFFICIENT_BUFFER;
6840                 goto out;
6841         }
6842
6843         if (!rpcbuf_alloc_size(buffer, *needed)) {
6844                 result = WERR_NOMEM;    
6845                 goto out;
6846         }
6847
6848         /* fill the buffer with the form structures */
6849         for (i=0; i<*returned; i++) {
6850                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6851                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6852         }
6853
6854 out:
6855         SAFE_FREE(driver_info_2);
6856
6857         if ( !W_ERROR_IS_OK(result) )
6858                 *returned = 0;
6859
6860         return result;
6861 }
6862
6863 /****************************************************************************
6864  Enumerates all printer drivers at level 3.
6865 ****************************************************************************/
6866
6867 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6868 {
6869         int i;
6870         int ndrivers;
6871         uint32 version;
6872         fstring *list = NULL;
6873         DRIVER_INFO_3 *driver_info_3=NULL;
6874         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6875         WERROR result = WERR_OK;
6876
6877         *returned=0;
6878
6879         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6880                 list=NULL;
6881                 ndrivers=get_ntdrivers(&list, architecture, version);
6882                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6883
6884                 if(ndrivers == -1) {
6885                         SAFE_FREE(driver_info_3);
6886                         return WERR_NOMEM;
6887                 }
6888
6889                 if(ndrivers != 0) {
6890                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6891                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6892                                 SAFE_FREE(list);
6893                                 return WERR_NOMEM;
6894                         }
6895                 }
6896
6897                 for (i=0; i<ndrivers; i++) {
6898                         WERROR status;
6899
6900                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6901                         ZERO_STRUCT(driver);
6902                         status = get_a_printer_driver(&driver, 3, list[i], 
6903                                                       architecture, version);
6904                         if (!W_ERROR_IS_OK(status)) {
6905                                 SAFE_FREE(list);
6906                                 SAFE_FREE(driver_info_3);
6907                                 return status;
6908                         }
6909                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
6910                         free_a_printer_driver(driver, 3);
6911                 }       
6912
6913                 *returned+=ndrivers;
6914                 SAFE_FREE(list);
6915         }
6916
6917         /* check the required size. */
6918         for (i=0; i<*returned; i++) {
6919                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6920                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6921         }
6922
6923         if (*needed > offered) {
6924                 result = WERR_INSUFFICIENT_BUFFER;
6925                 goto out;
6926         }
6927
6928         if (!rpcbuf_alloc_size(buffer, *needed)) {
6929                 result = WERR_NOMEM;    
6930                 goto out;
6931         }
6932
6933         /* fill the buffer with the driver structures */
6934         for (i=0; i<*returned; i++) {
6935                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6936                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6937         }
6938
6939 out:
6940         for (i=0; i<*returned; i++) {
6941                 SAFE_FREE(driver_info_3[i].dependentfiles);
6942         }
6943
6944         SAFE_FREE(driver_info_3);
6945         
6946         if ( !W_ERROR_IS_OK(result) )
6947                 *returned = 0;
6948
6949         return result;
6950 }
6951
6952 /****************************************************************************
6953  Enumerates all printer drivers.
6954 ****************************************************************************/
6955
6956 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6957 {
6958         uint32 level = q_u->level;
6959         RPC_BUFFER *buffer = NULL;
6960         uint32 offered = q_u->offered;
6961         uint32 *needed = &r_u->needed;
6962         uint32 *returned = &r_u->returned;
6963
6964         fstring servername;
6965         fstring architecture;
6966
6967         /* that's an [in out] buffer */
6968
6969         if (!q_u->buffer && (offered!=0)) {
6970                 return WERR_INVALID_PARAM;
6971         }
6972
6973         rpcbuf_move(q_u->buffer, &r_u->buffer);
6974         buffer = r_u->buffer;
6975
6976         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6977         
6978         *needed   = 0;
6979         *returned = 0;
6980
6981         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6982         unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6983
6984         if ( !is_myname_or_ipaddr( servername ) )
6985                 return WERR_UNKNOWN_PRINTER_DRIVER;
6986
6987         switch (level) {
6988         case 1:
6989                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6990         case 2:
6991                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6992         case 3:
6993                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6994         default:
6995                 return WERR_UNKNOWN_LEVEL;
6996         }
6997 }
6998
6999 /****************************************************************************
7000 ****************************************************************************/
7001
7002 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7003 {
7004         form->flag=list->flag;
7005         init_unistr(&form->name, list->name);
7006         form->width=list->width;
7007         form->length=list->length;
7008         form->left=list->left;
7009         form->top=list->top;
7010         form->right=list->right;
7011         form->bottom=list->bottom;      
7012 }
7013         
7014 /****************************************************************************
7015 ****************************************************************************/
7016
7017 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7018 {
7019         uint32 level = q_u->level;
7020         RPC_BUFFER *buffer = NULL;
7021         uint32 offered = q_u->offered;
7022         uint32 *needed = &r_u->needed;
7023         uint32 *numofforms = &r_u->numofforms;
7024         uint32 numbuiltinforms;
7025
7026         nt_forms_struct *list=NULL;
7027         nt_forms_struct *builtinlist=NULL;
7028         FORM_1 *forms_1;
7029         int buffer_size=0;
7030         int i;
7031
7032         /* that's an [in out] buffer */
7033
7034         if (!q_u->buffer && (offered!=0) ) {
7035                 return WERR_INVALID_PARAM;
7036         }
7037
7038         rpcbuf_move(q_u->buffer, &r_u->buffer);
7039         buffer = r_u->buffer;
7040
7041         DEBUG(4,("_spoolss_enumforms\n"));
7042         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7043         DEBUGADD(5,("Info level [%d]\n",          level));
7044
7045         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7046         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7047         *numofforms = get_ntforms(&list);
7048         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7049         *numofforms += numbuiltinforms;
7050
7051         if (*numofforms == 0) {
7052                 SAFE_FREE(builtinlist);
7053                 SAFE_FREE(list);
7054                 return WERR_NO_MORE_ITEMS;
7055         }
7056
7057         switch (level) {
7058         case 1:
7059                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7060                         SAFE_FREE(builtinlist);
7061                         SAFE_FREE(list);
7062                         *numofforms=0;
7063                         return WERR_NOMEM;
7064                 }
7065
7066                 /* construct the list of form structures */
7067                 for (i=0; i<numbuiltinforms; i++) {
7068                         DEBUGADD(6,("Filling form number [%d]\n",i));
7069                         fill_form_1(&forms_1[i], &builtinlist[i]);
7070                 }
7071                 
7072                 SAFE_FREE(builtinlist);
7073
7074                 for (; i<*numofforms; i++) {
7075                         DEBUGADD(6,("Filling form number [%d]\n",i));
7076                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7077                 }
7078                 
7079                 SAFE_FREE(list);
7080
7081                 /* check the required size. */
7082                 for (i=0; i<numbuiltinforms; i++) {
7083                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7084                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7085                 }
7086                 for (; i<*numofforms; i++) {
7087                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7088                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7089                 }
7090
7091                 *needed=buffer_size;            
7092                 
7093                 if (*needed > offered) {
7094                         SAFE_FREE(forms_1);
7095                         *numofforms=0;
7096                         return WERR_INSUFFICIENT_BUFFER;
7097                 }
7098         
7099                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7100                         SAFE_FREE(forms_1);
7101                         *numofforms=0;
7102                         return WERR_NOMEM;
7103                 }
7104
7105                 /* fill the buffer with the form structures */
7106                 for (i=0; i<numbuiltinforms; i++) {
7107                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7108                         smb_io_form_1("", buffer, &forms_1[i], 0);
7109                 }
7110                 for (; i<*numofforms; i++) {
7111                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7112                         smb_io_form_1("", buffer, &forms_1[i], 0);
7113                 }
7114
7115                 SAFE_FREE(forms_1);
7116
7117                 return WERR_OK;
7118                         
7119         default:
7120                 SAFE_FREE(list);
7121                 SAFE_FREE(builtinlist);
7122                 return WERR_UNKNOWN_LEVEL;
7123         }
7124 }
7125
7126 /****************************************************************************
7127 ****************************************************************************/
7128
7129 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7130 {
7131         uint32 level = q_u->level;
7132         UNISTR2 *uni_formname = &q_u->formname;
7133         RPC_BUFFER *buffer = NULL;
7134         uint32 offered = q_u->offered;
7135         uint32 *needed = &r_u->needed;
7136
7137         nt_forms_struct *list=NULL;
7138         nt_forms_struct builtin_form;
7139         BOOL foundBuiltin;
7140         FORM_1 form_1;
7141         fstring form_name;
7142         int buffer_size=0;
7143         int numofforms=0, i=0;
7144
7145         /* that's an [in out] buffer */
7146
7147         if (!q_u->buffer && (offered!=0)) {
7148                 return WERR_INVALID_PARAM;
7149         }
7150
7151         rpcbuf_move(q_u->buffer, &r_u->buffer);
7152         buffer = r_u->buffer;
7153
7154         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7155
7156         DEBUG(4,("_spoolss_getform\n"));
7157         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7158         DEBUGADD(5,("Info level [%d]\n",          level));
7159
7160         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7161         if (!foundBuiltin) {
7162                 numofforms = get_ntforms(&list);
7163                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7164
7165                 if (numofforms == 0)
7166                         return WERR_BADFID;
7167         }
7168
7169         switch (level) {
7170         case 1:
7171                 if (foundBuiltin) {
7172                         fill_form_1(&form_1, &builtin_form);
7173                 } else {
7174
7175                         /* Check if the requested name is in the list of form structures */
7176                         for (i=0; i<numofforms; i++) {
7177
7178                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7179
7180                                 if (strequal(form_name, list[i].name)) {
7181                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7182                                         fill_form_1(&form_1, &list[i]);
7183                                         break;
7184                                 }
7185                         }
7186                         
7187                         SAFE_FREE(list);
7188                         if (i == numofforms) {
7189                                 return WERR_BADFID;
7190                         }
7191                 }
7192                 /* check the required size. */
7193
7194                 *needed=spoolss_size_form_1(&form_1);
7195                 
7196                 if (*needed > offered) 
7197                         return WERR_INSUFFICIENT_BUFFER;
7198
7199                 if (!rpcbuf_alloc_size(buffer, buffer_size))
7200                         return WERR_NOMEM;
7201
7202                 /* fill the buffer with the form structures */
7203                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7204                 smb_io_form_1("", buffer, &form_1, 0);
7205
7206                 return WERR_OK;
7207                         
7208         default:
7209                 SAFE_FREE(list);
7210                 return WERR_UNKNOWN_LEVEL;
7211         }
7212 }
7213
7214 /****************************************************************************
7215 ****************************************************************************/
7216
7217 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7218 {
7219         init_unistr(&port->port_name, name);
7220 }
7221
7222 /****************************************************************************
7223  TODO: This probably needs distinguish between TCP/IP and Local ports 
7224  somehow.
7225 ****************************************************************************/
7226
7227 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7228 {
7229         init_unistr(&port->port_name, name);
7230         init_unistr(&port->monitor_name, "Local Monitor");
7231         init_unistr(&port->description, SPL_LOCAL_PORT );
7232         port->port_type=PORT_TYPE_WRITE;
7233         port->reserved=0x0;     
7234 }
7235
7236
7237 /****************************************************************************
7238  wrapper around the enumer ports command
7239 ****************************************************************************/
7240
7241 WERROR enumports_hook( int *count, char ***lines )
7242 {
7243         char *cmd = lp_enumports_cmd();
7244         char **qlines;
7245         pstring command;
7246         int numlines;
7247         int ret;
7248         int fd;
7249
7250         *count = 0;
7251         *lines = NULL;
7252
7253         /* if no hook then just fill in the default port */
7254         
7255         if ( !*cmd ) {
7256                 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7257                 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7258                 qlines[1] = NULL;
7259                 numlines = 1;
7260         }
7261         else {
7262                 /* we have a valid enumport command */
7263                 
7264                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7265
7266                 DEBUG(10,("Running [%s]\n", command));
7267                 ret = smbrun(command, &fd);
7268                 DEBUG(10,("Returned [%d]\n", ret));
7269                 if (ret != 0) {
7270                         if (fd != -1) {
7271                                 close(fd);
7272                         }
7273                         return WERR_ACCESS_DENIED;
7274                 }
7275
7276                 numlines = 0;
7277                 qlines = fd_lines_load(fd, &numlines, 0);
7278                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7279                 close(fd);
7280         }
7281         
7282         *count = numlines;
7283         *lines = qlines;
7284
7285         return WERR_OK;
7286 }
7287
7288 /****************************************************************************
7289  enumports level 1.
7290 ****************************************************************************/
7291
7292 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7293 {
7294         PORT_INFO_1 *ports=NULL;
7295         int i=0;
7296         WERROR result = WERR_OK;
7297         char **qlines = NULL;
7298         int numlines = 0;
7299
7300         result = enumports_hook( &numlines, &qlines );
7301         if (!W_ERROR_IS_OK(result)) {
7302                 file_lines_free(qlines);
7303                 return result;
7304         }
7305         
7306         if(numlines) {
7307                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7308                         DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
7309                                   dos_errstr(WERR_NOMEM)));
7310                         file_lines_free(qlines);
7311                         return WERR_NOMEM;
7312                 }
7313
7314                 for (i=0; i<numlines; i++) {
7315                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7316                         fill_port_1(&ports[i], qlines[i]);
7317                 }
7318         }
7319         file_lines_free(qlines);
7320
7321         *returned = numlines;
7322
7323         /* check the required size. */
7324         for (i=0; i<*returned; i++) {
7325                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7326                 *needed += spoolss_size_port_info_1(&ports[i]);
7327         }
7328                 
7329         if (*needed > offered) {
7330                 result = WERR_INSUFFICIENT_BUFFER;
7331                 goto out;
7332         }
7333
7334         if (!rpcbuf_alloc_size(buffer, *needed)) {
7335                 result = WERR_NOMEM;
7336                 goto out;
7337         }
7338
7339         /* fill the buffer with the ports structures */
7340         for (i=0; i<*returned; i++) {
7341                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7342                 smb_io_port_1("", buffer, &ports[i], 0);
7343         }
7344
7345 out:
7346         SAFE_FREE(ports);
7347
7348         if ( !W_ERROR_IS_OK(result) )
7349                 *returned = 0;
7350
7351         return result;
7352 }
7353
7354 /****************************************************************************
7355  enumports level 2.
7356 ****************************************************************************/
7357
7358 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7359 {
7360         PORT_INFO_2 *ports=NULL;
7361         int i=0;
7362         WERROR result = WERR_OK;
7363         char **qlines = NULL;
7364         int numlines = 0;
7365
7366         result = enumports_hook( &numlines, &qlines );
7367         if ( !W_ERROR_IS_OK(result)) {
7368                 file_lines_free(qlines);
7369                 return result;
7370         }
7371         
7372         if(numlines) {
7373                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7374                         file_lines_free(qlines);
7375                         return WERR_NOMEM;
7376                 }
7377
7378                 for (i=0; i<numlines; i++) {
7379                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7380                         fill_port_2(&(ports[i]), qlines[i]);
7381                 }
7382         }
7383
7384         file_lines_free(qlines);
7385
7386         *returned = numlines;
7387
7388         /* check the required size. */
7389         for (i=0; i<*returned; i++) {
7390                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7391                 *needed += spoolss_size_port_info_2(&ports[i]);
7392         }
7393                 
7394         if (*needed > offered) {
7395                 result = WERR_INSUFFICIENT_BUFFER;
7396                 goto out;
7397         }
7398
7399         if (!rpcbuf_alloc_size(buffer, *needed)) {
7400                 result = WERR_NOMEM;
7401                 goto out;
7402         }
7403
7404         /* fill the buffer with the ports structures */
7405         for (i=0; i<*returned; i++) {
7406                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7407                 smb_io_port_2("", buffer, &ports[i], 0);
7408         }
7409
7410 out:
7411         SAFE_FREE(ports);
7412
7413         if ( !W_ERROR_IS_OK(result) )
7414                 *returned = 0;
7415
7416         return result;
7417 }
7418
7419 /****************************************************************************
7420  enumports.
7421 ****************************************************************************/
7422
7423 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7424 {
7425         uint32 level = q_u->level;
7426         RPC_BUFFER *buffer = NULL;
7427         uint32 offered = q_u->offered;
7428         uint32 *needed = &r_u->needed;
7429         uint32 *returned = &r_u->returned;
7430
7431         /* that's an [in out] buffer */
7432
7433         if (!q_u->buffer && (offered!=0)) {
7434                 return WERR_INVALID_PARAM;
7435         }
7436
7437         rpcbuf_move(q_u->buffer, &r_u->buffer);
7438         buffer = r_u->buffer;
7439
7440         DEBUG(4,("_spoolss_enumports\n"));
7441         
7442         *returned=0;
7443         *needed=0;
7444         
7445         switch (level) {
7446         case 1:
7447                 return enumports_level_1(buffer, offered, needed, returned);
7448         case 2:
7449                 return enumports_level_2(buffer, offered, needed, returned);
7450         default:
7451                 return WERR_UNKNOWN_LEVEL;
7452         }
7453 }
7454
7455 /****************************************************************************
7456 ****************************************************************************/
7457
7458 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7459                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7460                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7461                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7462                                 POLICY_HND *handle)
7463 {
7464         NT_PRINTER_INFO_LEVEL *printer = NULL;
7465         fstring name;
7466         int     snum;
7467         WERROR err = WERR_OK;
7468
7469         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7470                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7471                 return WERR_NOMEM;
7472         }
7473
7474         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7475         if (!convert_printer_info(info, printer, 2)) {
7476                 free_a_printer(&printer, 2);
7477                 return WERR_NOMEM;
7478         }
7479
7480         /* check to see if the printer already exists */
7481
7482         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7483                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n", 
7484                         printer->info_2->sharename));
7485                 free_a_printer(&printer, 2);
7486                 return WERR_PRINTER_ALREADY_EXISTS;
7487         }
7488         
7489         /* FIXME!!!  smbd should check to see if the driver is installed before
7490            trying to add a printer like this  --jerry */
7491
7492         if (*lp_addprinter_cmd() ) {
7493                 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7494                         free_a_printer(&printer,2);
7495                         return WERR_ACCESS_DENIED;
7496                 }
7497         } else {
7498                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7499                         "smb.conf parameter \"addprinter command\" is defined. This"
7500                         "parameter must exist for this call to succeed\n",
7501                         printer->info_2->sharename ));
7502         }
7503
7504         /* use our primary netbios name since get_a_printer() will convert 
7505            it to what the client expects on a case by case basis */
7506
7507         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7508              printer->info_2->sharename);
7509
7510         
7511         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7512                 free_a_printer(&printer,2);
7513                 return WERR_ACCESS_DENIED;
7514         }
7515
7516         /* you must be a printer admin to add a new printer */
7517         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7518                 free_a_printer(&printer,2);
7519                 return WERR_ACCESS_DENIED;              
7520         }
7521         
7522         /*
7523          * Do sanity check on the requested changes for Samba.
7524          */
7525
7526         if (!check_printer_ok(printer->info_2, snum)) {
7527                 free_a_printer(&printer,2);
7528                 return WERR_INVALID_PARAM;
7529         }
7530
7531         /*
7532          * When a printer is created, the drivername bound to the printer is used
7533          * to lookup previously saved driver initialization info, which is then 
7534          * bound to the new printer, simulating what happens in the Windows arch.
7535          */
7536
7537         if (!devmode)
7538         {
7539                 set_driver_init(printer, 2);
7540         }
7541         else 
7542         {
7543                 /* A valid devmode was included, convert and link it
7544                 */
7545                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7546
7547                 if (!convert_devicemode(printer->info_2->printername, devmode,
7548                                 &printer->info_2->devmode))
7549                         return  WERR_NOMEM;
7550         }
7551
7552         /* write the ASCII on disk */
7553         err = mod_a_printer(printer, 2);
7554         if (!W_ERROR_IS_OK(err)) {
7555                 free_a_printer(&printer,2);
7556                 return err;
7557         }
7558
7559         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7560                 /* Handle open failed - remove addition. */
7561                 del_a_printer(printer->info_2->sharename);
7562                 free_a_printer(&printer,2);
7563                 return WERR_ACCESS_DENIED;
7564         }
7565
7566         update_c_setprinter(False);
7567         free_a_printer(&printer,2);
7568
7569         return WERR_OK;
7570 }
7571
7572 /****************************************************************************
7573 ****************************************************************************/
7574
7575 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7576 {
7577         UNISTR2 *uni_srv_name = q_u->server_name;
7578         uint32 level = q_u->level;
7579         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7580         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7581         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7582         uint32 user_switch = q_u->user_switch;
7583         SPOOL_USER_CTR *user = &q_u->user_ctr;
7584         POLICY_HND *handle = &r_u->handle;
7585
7586         switch (level) {
7587                 case 1:
7588                         /* we don't handle yet */
7589                         /* but I know what to do ... */
7590                         return WERR_UNKNOWN_LEVEL;
7591                 case 2:
7592                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7593                                                             devmode, sdb,
7594                                                             user_switch, user, handle);
7595                 default:
7596                         return WERR_UNKNOWN_LEVEL;
7597         }
7598 }
7599
7600 /****************************************************************************
7601 ****************************************************************************/
7602
7603 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7604 {
7605         uint32 level = q_u->level;
7606         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7607         WERROR err = WERR_OK;
7608         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7609         struct current_user user;
7610         fstring driver_name;
7611         uint32 version;
7612
7613         ZERO_STRUCT(driver);
7614
7615         get_current_user(&user, p);
7616         
7617         if (!convert_printer_driver_info(info, &driver, level)) {
7618                 err = WERR_NOMEM;
7619                 goto done;
7620         }
7621
7622         DEBUG(5,("Cleaning driver's information\n"));
7623         err = clean_up_driver_struct(driver, level, &user);
7624         if (!W_ERROR_IS_OK(err))
7625                 goto done;
7626
7627         DEBUG(5,("Moving driver to final destination\n"));
7628         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7629                 goto done;
7630         }
7631
7632         if (add_a_printer_driver(driver, level)!=0) {
7633                 err = WERR_ACCESS_DENIED;
7634                 goto done;
7635         }
7636
7637         /* BEGIN_ADMIN_LOG */
7638         switch(level) {
7639             case 3:
7640                 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7641                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7642                         driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7643                 break;
7644             case 6:   
7645                 fstrcpy(driver_name, driver.info_6->name ?  driver.info_6->name : "");
7646                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7647                         driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7648                 break;
7649         }
7650         /* END_ADMIN_LOG */
7651
7652         /* 
7653          * I think this is where he DrvUpgradePrinter() hook would be
7654          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7655          * server.  Right now, we just need to send ourselves a message
7656          * to update each printer bound to this driver.   --jerry       
7657          */
7658          
7659         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7660                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7661                         driver_name));
7662         }
7663
7664         /*
7665          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7666          * decide if the driver init data should be deleted. The rules are:
7667          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7668          *  2) delete init data only if there is no 2k/Xp driver
7669          *  3) always delete init data
7670          * The generalized rule is always use init data from the highest order driver.
7671          * It is necessary to follow the driver install by an initialization step to
7672          * finish off this process.
7673         */
7674         if (level == 3)
7675                 version = driver.info_3->cversion;
7676         else if (level == 6)
7677                 version = driver.info_6->version;
7678         else
7679                 version = -1;
7680         switch (version) {
7681                 /*
7682                  * 9x printer driver - never delete init data
7683                 */
7684                 case 0: 
7685                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7686                                         driver_name));
7687                         break;
7688                 
7689                 /*
7690                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7691                  * there is no 2k/Xp driver init data for this driver name.
7692                 */
7693                 case 2:
7694                 {
7695                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7696
7697                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7698                                 /*
7699                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7700                                 */
7701                                 if (!del_driver_init(driver_name))
7702                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7703                         } else {
7704                                 /*
7705                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7706                                 */
7707                                 free_a_printer_driver(driver1,3);
7708                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", 
7709                                                 driver_name));
7710                         }
7711                 }
7712                 break;
7713
7714                 /*
7715                  * 2k or Xp printer driver - always delete init data
7716                 */
7717                 case 3: 
7718                         if (!del_driver_init(driver_name))
7719                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7720                         break;
7721
7722                 default:
7723                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7724                         break;
7725         }
7726
7727         
7728 done:
7729         free_a_printer_driver(driver, level);
7730         return err;
7731 }
7732
7733 /********************************************************************
7734  * spoolss_addprinterdriverex
7735  ********************************************************************/
7736
7737 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7738 {
7739         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7740         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7741         
7742         /* 
7743          * we only support the semantics of AddPrinterDriver()
7744          * i.e. only copy files that are newer than existing ones
7745          */
7746         
7747         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7748                 return WERR_ACCESS_DENIED;
7749         
7750         ZERO_STRUCT(q_u_local);
7751         ZERO_STRUCT(r_u_local);
7752
7753         /* just pass the information off to _spoolss_addprinterdriver() */
7754         q_u_local.server_name_ptr = q_u->server_name_ptr;
7755         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7756         q_u_local.level = q_u->level;
7757         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7758         
7759         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7760 }
7761
7762 /****************************************************************************
7763 ****************************************************************************/
7764
7765 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7766 {
7767         init_unistr(&info->name, name);
7768 }
7769
7770 /****************************************************************************
7771 ****************************************************************************/
7772
7773 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7774 {
7775         pstring path;
7776         pstring long_archi;
7777         fstring servername;
7778         char *pservername; 
7779         const char *short_archi;
7780         DRIVER_DIRECTORY_1 *info=NULL;
7781         WERROR result = WERR_OK;
7782
7783         unistr2_to_ascii(servername, name, sizeof(servername)-1);
7784         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7785
7786         /* check for beginning double '\'s and that the server
7787            long enough */
7788
7789         pservername = servername;
7790         if ( *pservername == '\\' && strlen(servername)>2 ) {
7791                 pservername += 2;
7792         } 
7793         
7794         if ( !is_myname_or_ipaddr( pservername ) )
7795                 return WERR_INVALID_PARAM;
7796
7797         if (!(short_archi = get_short_archi(long_archi)))
7798                 return WERR_INVALID_ENVIRONMENT;
7799
7800         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7801                 return WERR_NOMEM;
7802
7803         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7804
7805         DEBUG(4,("printer driver directory: [%s]\n", path));
7806
7807         fill_driverdir_1(info, path);
7808         
7809         *needed += spoolss_size_driverdir_info_1(info);
7810
7811         if (*needed > offered) {
7812                 result = WERR_INSUFFICIENT_BUFFER;
7813                 goto out;
7814         }
7815
7816         if (!rpcbuf_alloc_size(buffer, *needed)) {
7817                 result = WERR_NOMEM;
7818                 goto out;
7819         }
7820
7821         smb_io_driverdir_1("", buffer, info, 0);
7822
7823 out:
7824         SAFE_FREE(info);
7825         
7826         return result;
7827 }
7828
7829 /****************************************************************************
7830 ****************************************************************************/
7831
7832 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7833 {
7834         UNISTR2 *name = &q_u->name;
7835         UNISTR2 *uni_environment = &q_u->environment;
7836         uint32 level = q_u->level;
7837         RPC_BUFFER *buffer = NULL;
7838         uint32 offered = q_u->offered;
7839         uint32 *needed = &r_u->needed;
7840
7841         /* that's an [in out] buffer */
7842
7843         if (!q_u->buffer && (offered!=0)) {
7844                 return WERR_INVALID_PARAM;
7845         }
7846
7847         rpcbuf_move(q_u->buffer, &r_u->buffer);
7848         buffer = r_u->buffer;
7849
7850         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7851
7852         *needed=0;
7853
7854         switch(level) {
7855         case 1:
7856                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7857         default:
7858                 return WERR_UNKNOWN_LEVEL;
7859         }
7860 }
7861         
7862 /****************************************************************************
7863 ****************************************************************************/
7864
7865 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7866 {
7867         POLICY_HND *handle = &q_u->handle;
7868         uint32 idx               = q_u->index;
7869         uint32 in_value_len      = q_u->valuesize;
7870         uint32 in_data_len       = q_u->datasize;
7871         uint32 *out_max_value_len = &r_u->valuesize;
7872         uint16 **out_value       = &r_u->value;
7873         uint32 *out_value_len    = &r_u->realvaluesize;
7874         uint32 *out_type         = &r_u->type;
7875         uint32 *out_max_data_len = &r_u->datasize;
7876         uint8  **data_out        = &r_u->data;
7877         uint32 *out_data_len     = &r_u->realdatasize;
7878
7879         NT_PRINTER_INFO_LEVEL *printer = NULL;
7880         
7881         uint32          biggest_valuesize;
7882         uint32          biggest_datasize;
7883         uint32          data_len;
7884         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7885         int             snum;
7886         WERROR          result;
7887         REGISTRY_VALUE  *val = NULL;
7888         NT_PRINTER_DATA *p_data;
7889         int             i, key_index, num_values;
7890         int             name_length;
7891         
7892         *out_type = 0;
7893
7894         *out_max_data_len = 0;
7895         *data_out         = NULL;
7896         *out_data_len     = 0;
7897
7898         DEBUG(5,("spoolss_enumprinterdata\n"));
7899
7900         if (!Printer) {
7901                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7902                 return WERR_BADFID;
7903         }
7904
7905         if (!get_printer_snum(p,handle, &snum))
7906                 return WERR_BADFID;
7907         
7908         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7909         if (!W_ERROR_IS_OK(result))
7910                 return result;
7911                 
7912         p_data = printer->info_2->data; 
7913         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7914
7915         result = WERR_OK;
7916
7917         /*
7918          * The NT machine wants to know the biggest size of value and data
7919          *
7920          * cf: MSDN EnumPrinterData remark section
7921          */
7922          
7923         if ( !in_value_len && !in_data_len && (key_index != -1) ) 
7924         {
7925                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7926
7927                 biggest_valuesize = 0;
7928                 biggest_datasize  = 0;
7929                                 
7930                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7931         
7932                 for ( i=0; i<num_values; i++ )
7933                 {
7934                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7935                         
7936                         name_length = strlen(val->valuename);
7937                         if ( strlen(val->valuename) > biggest_valuesize ) 
7938                                 biggest_valuesize = name_length;
7939                                 
7940                         if ( val->size > biggest_datasize )
7941                                 biggest_datasize = val->size;
7942                                 
7943                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, 
7944                                 biggest_datasize));
7945                 }
7946
7947                 /* the value is an UNICODE string but real_value_size is the length 
7948                    in bytes including the trailing 0 */
7949                    
7950                 *out_value_len = 2 * (1+biggest_valuesize);
7951                 *out_data_len  = biggest_datasize;
7952
7953                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7954
7955                 goto done;
7956         }
7957         
7958         /*
7959          * the value len is wrong in NT sp3
7960          * that's the number of bytes not the number of unicode chars
7961          */
7962         
7963         if ( key_index != -1 )
7964                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7965
7966         if ( !val ) 
7967         {
7968
7969                 /* out_value should default to "" or else NT4 has
7970                    problems unmarshalling the response */
7971
7972                 *out_max_value_len=(in_value_len/sizeof(uint16));
7973                 
7974                 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7975                 {
7976                         result = WERR_NOMEM;
7977                         goto done;
7978                 }
7979
7980                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7981
7982                 /* the data is counted in bytes */
7983                 
7984                 *out_max_data_len = in_data_len;
7985                 *out_data_len     = in_data_len;
7986                 
7987                 /* only allocate when given a non-zero data_len */
7988                 
7989                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7990                 {
7991                         result = WERR_NOMEM;
7992                         goto done;
7993                 }
7994
7995                 result = WERR_NO_MORE_ITEMS;
7996         }
7997         else 
7998         {
7999                 /*
8000                  * the value is:
8001                  * - counted in bytes in the request
8002                  * - counted in UNICODE chars in the max reply
8003                  * - counted in bytes in the real size
8004                  *
8005                  * take a pause *before* coding not *during* coding
8006                  */
8007         
8008                 /* name */
8009                 *out_max_value_len=(in_value_len/sizeof(uint16));
8010                 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
8011                 {
8012                         result = WERR_NOMEM;
8013                         goto done;
8014                 }
8015         
8016                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8017
8018                 /* type */
8019                 
8020                 *out_type = regval_type( val );
8021
8022                 /* data - counted in bytes */
8023
8024                 *out_max_data_len = in_data_len;
8025                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
8026                 {
8027                         result = WERR_NOMEM;
8028                         goto done;
8029                 }
8030                 data_len = regval_size(val);
8031                 if ( *data_out )
8032                         memcpy( *data_out, regval_data_p(val), data_len );
8033                 *out_data_len = data_len;
8034         }
8035
8036 done:
8037         free_a_printer(&printer, 2);
8038         return result;
8039 }
8040
8041 /****************************************************************************
8042 ****************************************************************************/
8043
8044 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8045 {
8046         POLICY_HND              *handle = &q_u->handle;
8047         UNISTR2                 *value = &q_u->value;
8048         uint32                  type = q_u->type;
8049         uint8                   *data = q_u->data;
8050         uint32                  real_len = q_u->real_len;
8051
8052         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8053         int                     snum=0;
8054         WERROR                  status = WERR_OK;
8055         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8056         fstring                 valuename;
8057         
8058         DEBUG(5,("spoolss_setprinterdata\n"));
8059
8060         if (!Printer) {
8061                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8062                 return WERR_BADFID;
8063         }
8064
8065         if ( Printer->printer_type == SPLHND_SERVER ) {
8066                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8067                 return WERR_INVALID_PARAM;
8068         }
8069
8070         if (!get_printer_snum(p,handle, &snum))
8071                 return WERR_BADFID;
8072
8073         /* 
8074          * Access check : NT returns "access denied" if you make a 
8075          * SetPrinterData call without the necessary privildge.
8076          * we were originally returning OK if nothing changed
8077          * which made Win2k issue **a lot** of SetPrinterData
8078          * when connecting to a printer  --jerry
8079          */
8080
8081         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8082         {
8083                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8084                 status = WERR_ACCESS_DENIED;
8085                 goto done;
8086         }
8087
8088         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8089         if (!W_ERROR_IS_OK(status))
8090                 return status;
8091
8092         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8093         
8094         /*
8095          * When client side code sets a magic printer data key, detect it and save
8096          * the current printer data and the magic key's data (its the DEVMODE) for
8097          * future printer/driver initializations.
8098          */
8099         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
8100         {
8101                 /* Set devmode and printer initialization info */
8102                 status = save_driver_init( printer, 2, data, real_len );
8103         
8104                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8105         }
8106         else 
8107         {
8108         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
8109                                         type, data, real_len );
8110                 if ( W_ERROR_IS_OK(status) )
8111                         status = mod_a_printer(printer, 2);
8112         }
8113
8114 done:
8115         free_a_printer(&printer, 2);
8116
8117         return status;
8118 }
8119
8120 /****************************************************************************
8121 ****************************************************************************/
8122
8123 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8124 {
8125         POLICY_HND      *handle = &q_u->handle;
8126         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8127         int             snum;
8128         
8129         DEBUG(5,("_spoolss_resetprinter\n"));
8130
8131         /*
8132          * All we do is to check to see if the handle and queue is valid.
8133          * This call really doesn't mean anything to us because we only
8134          * support RAW printing.   --jerry
8135          */
8136          
8137         if (!Printer) {
8138                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8139                 return WERR_BADFID;
8140         }
8141
8142         if (!get_printer_snum(p,handle, &snum))
8143                 return WERR_BADFID;
8144
8145
8146         /* blindly return success */    
8147         return WERR_OK;
8148 }
8149
8150
8151 /****************************************************************************
8152 ****************************************************************************/
8153
8154 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8155 {
8156         POLICY_HND      *handle = &q_u->handle;
8157         UNISTR2         *value = &q_u->valuename;
8158
8159         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8160         int             snum=0;
8161         WERROR          status = WERR_OK;
8162         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8163         pstring         valuename;
8164         
8165         DEBUG(5,("spoolss_deleteprinterdata\n"));
8166         
8167         if (!Printer) {
8168                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8169                 return WERR_BADFID;
8170         }
8171
8172         if (!get_printer_snum(p, handle, &snum))
8173                 return WERR_BADFID;
8174
8175         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8176                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8177                 return WERR_ACCESS_DENIED;
8178         }
8179
8180         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8181         if (!W_ERROR_IS_OK(status))
8182                 return status;
8183
8184         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8185
8186         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8187         
8188         if ( W_ERROR_IS_OK(status) )
8189                 mod_a_printer( printer, 2 );
8190
8191         free_a_printer(&printer, 2);
8192
8193         return status;
8194 }
8195
8196 /****************************************************************************
8197 ****************************************************************************/
8198
8199 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8200 {
8201         POLICY_HND *handle = &q_u->handle;
8202         FORM *form = &q_u->form;
8203         nt_forms_struct tmpForm;
8204         int snum;
8205         WERROR status = WERR_OK;
8206         NT_PRINTER_INFO_LEVEL *printer = NULL;
8207
8208         int count=0;
8209         nt_forms_struct *list=NULL;
8210         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8211
8212         DEBUG(5,("spoolss_addform\n"));
8213
8214         if (!Printer) {
8215                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8216                 return WERR_BADFID;
8217         }
8218         
8219         
8220         /* forms can be added on printer of on the print server handle */
8221         
8222         if ( Printer->printer_type == SPLHND_PRINTER )
8223         {
8224                 if (!get_printer_snum(p,handle, &snum))
8225                         return WERR_BADFID;
8226          
8227                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8228                 if (!W_ERROR_IS_OK(status))
8229                         goto done;
8230         }
8231
8232         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8233                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8234                 status = WERR_ACCESS_DENIED;
8235                 goto done;
8236         }
8237         
8238         /* can't add if builtin */
8239         
8240         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8241                 status = WERR_ALREADY_EXISTS;
8242                 goto done;
8243         }
8244
8245         count = get_ntforms(&list);
8246         
8247         if(!add_a_form(&list, form, &count)) {
8248                 status =  WERR_NOMEM;
8249                 goto done;
8250         }
8251         
8252         write_ntforms(&list, count);
8253         
8254         /*
8255          * ChangeID must always be set if this is a printer
8256          */
8257          
8258         if ( Printer->printer_type == SPLHND_PRINTER )
8259                 status = mod_a_printer(printer, 2);
8260         
8261 done:
8262         if ( printer )
8263                 free_a_printer(&printer, 2);
8264         SAFE_FREE(list);
8265
8266         return status;
8267 }
8268
8269 /****************************************************************************
8270 ****************************************************************************/
8271
8272 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8273 {
8274         POLICY_HND *handle = &q_u->handle;
8275         UNISTR2 *form_name = &q_u->name;
8276         nt_forms_struct tmpForm;
8277         int count=0;
8278         nt_forms_struct *list=NULL;
8279         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8280         int snum;
8281         WERROR status = WERR_OK;
8282         NT_PRINTER_INFO_LEVEL *printer = NULL;
8283
8284         DEBUG(5,("spoolss_deleteform\n"));
8285
8286         if (!Printer) {
8287                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8288                 return WERR_BADFID;
8289         }
8290
8291         /* forms can be deleted on printer of on the print server handle */
8292         
8293         if ( Printer->printer_type == SPLHND_PRINTER )
8294         {
8295                 if (!get_printer_snum(p,handle, &snum))
8296                         return WERR_BADFID;
8297          
8298                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8299                 if (!W_ERROR_IS_OK(status))
8300                         goto done;
8301         }
8302
8303         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8304                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8305                 status = WERR_ACCESS_DENIED;
8306                 goto done;
8307         }
8308
8309         /* can't delete if builtin */
8310         
8311         if (get_a_builtin_ntform(form_name,&tmpForm)) {
8312                 status = WERR_INVALID_PARAM;
8313                 goto done;
8314         }
8315
8316         count = get_ntforms(&list);
8317         
8318         if ( !delete_a_form(&list, form_name, &count, &status ))
8319                 goto done;
8320
8321         /*
8322          * ChangeID must always be set if this is a printer
8323          */
8324          
8325         if ( Printer->printer_type == SPLHND_PRINTER )
8326                 status = mod_a_printer(printer, 2);
8327         
8328 done:
8329         if ( printer )
8330                 free_a_printer(&printer, 2);
8331         SAFE_FREE(list);
8332
8333         return status;
8334 }
8335
8336 /****************************************************************************
8337 ****************************************************************************/
8338
8339 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8340 {
8341         POLICY_HND *handle = &q_u->handle;
8342         FORM *form = &q_u->form;
8343         nt_forms_struct tmpForm;
8344         int snum;
8345         WERROR status = WERR_OK;
8346         NT_PRINTER_INFO_LEVEL *printer = NULL;
8347
8348         int count=0;
8349         nt_forms_struct *list=NULL;
8350         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8351
8352         DEBUG(5,("spoolss_setform\n"));
8353
8354         if (!Printer) {
8355                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8356                 return WERR_BADFID;
8357         }
8358
8359         /* forms can be modified on printer of on the print server handle */
8360         
8361         if ( Printer->printer_type == SPLHND_PRINTER )
8362         {
8363                 if (!get_printer_snum(p,handle, &snum))
8364                         return WERR_BADFID;
8365          
8366                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8367                 if (!W_ERROR_IS_OK(status))
8368                         goto done;
8369         }
8370
8371         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8372                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8373                 status = WERR_ACCESS_DENIED;
8374                 goto done;
8375         }
8376
8377         /* can't set if builtin */
8378         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8379                 status = WERR_INVALID_PARAM;
8380                 goto done;
8381         }
8382
8383         count = get_ntforms(&list);
8384         update_a_form(&list, form, count);
8385         write_ntforms(&list, count);
8386
8387         /*
8388          * ChangeID must always be set if this is a printer
8389          */
8390          
8391         if ( Printer->printer_type == SPLHND_PRINTER )
8392                 status = mod_a_printer(printer, 2);
8393         
8394         
8395 done:
8396         if ( printer )
8397                 free_a_printer(&printer, 2);
8398         SAFE_FREE(list);
8399
8400         return status;
8401 }
8402
8403 /****************************************************************************
8404  enumprintprocessors level 1.
8405 ****************************************************************************/
8406
8407 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8408 {
8409         PRINTPROCESSOR_1 *info_1=NULL;
8410         WERROR result = WERR_OK;
8411         
8412         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8413                 return WERR_NOMEM;
8414
8415         (*returned) = 0x1;
8416         
8417         init_unistr(&info_1->name, "winprint");
8418
8419         *needed += spoolss_size_printprocessor_info_1(info_1);
8420
8421         if (*needed > offered) {
8422                 result = WERR_INSUFFICIENT_BUFFER;
8423                 goto out;
8424         }
8425
8426         if (!rpcbuf_alloc_size(buffer, *needed)) {
8427                 result = WERR_NOMEM;
8428                 goto out;
8429         }
8430
8431         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8432
8433 out:
8434         SAFE_FREE(info_1);
8435
8436         if ( !W_ERROR_IS_OK(result) )
8437                 *returned = 0;
8438
8439         return result;
8440 }
8441
8442 /****************************************************************************
8443 ****************************************************************************/
8444
8445 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8446 {
8447         uint32 level = q_u->level;
8448         RPC_BUFFER *buffer = NULL;
8449         uint32 offered = q_u->offered;
8450         uint32 *needed = &r_u->needed;
8451         uint32 *returned = &r_u->returned;
8452
8453         /* that's an [in out] buffer */
8454
8455         if (!q_u->buffer && (offered!=0)) {
8456                 return WERR_INVALID_PARAM;
8457         }
8458
8459         rpcbuf_move(q_u->buffer, &r_u->buffer);
8460         buffer = r_u->buffer;
8461
8462         DEBUG(5,("spoolss_enumprintprocessors\n"));
8463
8464         /*
8465          * Enumerate the print processors ...
8466          *
8467          * Just reply with "winprint", to keep NT happy
8468          * and I can use my nice printer checker.
8469          */
8470         
8471         *returned=0;
8472         *needed=0;
8473         
8474         switch (level) {
8475         case 1:
8476                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8477         default:
8478                 return WERR_UNKNOWN_LEVEL;
8479         }
8480 }
8481
8482 /****************************************************************************
8483  enumprintprocdatatypes level 1.
8484 ****************************************************************************/
8485
8486 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8487 {
8488         PRINTPROCDATATYPE_1 *info_1=NULL;
8489         WERROR result = WERR_NOMEM;
8490         
8491         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8492                 return WERR_NOMEM;
8493
8494         (*returned) = 0x1;
8495         
8496         init_unistr(&info_1->name, "RAW");
8497
8498         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8499
8500         if (*needed > offered) {
8501                 result = WERR_INSUFFICIENT_BUFFER;
8502                 goto out;
8503         }
8504
8505         if (!rpcbuf_alloc_size(buffer, *needed)) {
8506                 result = WERR_NOMEM;
8507                 goto out;
8508         }
8509
8510         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8511
8512 out:
8513         SAFE_FREE(info_1);
8514
8515         if ( !W_ERROR_IS_OK(result) )
8516                 *returned = 0;
8517
8518         return result;
8519 }
8520
8521 /****************************************************************************
8522 ****************************************************************************/
8523
8524 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8525 {
8526         uint32 level = q_u->level;
8527         RPC_BUFFER *buffer = NULL;
8528         uint32 offered = q_u->offered;
8529         uint32 *needed = &r_u->needed;
8530         uint32 *returned = &r_u->returned;
8531
8532         /* that's an [in out] buffer */
8533
8534         if (!q_u->buffer && (offered!=0)) {
8535                 return WERR_INVALID_PARAM;
8536         }
8537
8538         rpcbuf_move(q_u->buffer, &r_u->buffer);
8539         buffer = r_u->buffer;
8540
8541         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8542         
8543         *returned=0;
8544         *needed=0;
8545         
8546         switch (level) {
8547         case 1:
8548                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8549         default:
8550                 return WERR_UNKNOWN_LEVEL;
8551         }
8552 }
8553
8554 /****************************************************************************
8555  enumprintmonitors level 1.
8556 ****************************************************************************/
8557
8558 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8559 {
8560         PRINTMONITOR_1 *info_1;
8561         WERROR result = WERR_OK;
8562         int i;
8563         
8564         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8565                 return WERR_NOMEM;
8566
8567         *returned = 2;
8568         
8569         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT ); 
8570         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8571
8572         for ( i=0; i<*returned; i++ ) {
8573                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8574         }
8575         
8576         if (*needed > offered) {
8577                 result = WERR_INSUFFICIENT_BUFFER;
8578                 goto out;
8579         }
8580
8581         if (!rpcbuf_alloc_size(buffer, *needed)) {
8582                 result = WERR_NOMEM;
8583                 goto out;
8584         }
8585
8586         for ( i=0; i<*returned; i++ ) {
8587                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8588         }
8589
8590 out:
8591         SAFE_FREE(info_1);
8592
8593         if ( !W_ERROR_IS_OK(result) )
8594                 *returned = 0;
8595
8596         return result;
8597 }
8598
8599 /****************************************************************************
8600  enumprintmonitors level 2.
8601 ****************************************************************************/
8602
8603 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8604 {
8605         PRINTMONITOR_2 *info_2;
8606         WERROR result = WERR_OK;
8607         int i;
8608         
8609         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8610                 return WERR_NOMEM;
8611
8612         *returned = 2;
8613         
8614         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8615         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8616         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8617         
8618         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8619         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8620         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8621
8622         for ( i=0; i<*returned; i++ ) {
8623                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8624         }
8625         
8626         if (*needed > offered) {
8627                 result = WERR_INSUFFICIENT_BUFFER;
8628                 goto out;
8629         }
8630
8631         if (!rpcbuf_alloc_size(buffer, *needed)) {
8632                 result = WERR_NOMEM;
8633                 goto out;
8634         }
8635
8636         for ( i=0; i<*returned; i++ ) {
8637                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8638         }
8639
8640 out:
8641         SAFE_FREE(info_2);
8642
8643         if ( !W_ERROR_IS_OK(result) )
8644                 *returned = 0;
8645         
8646         return result;
8647 }
8648
8649 /****************************************************************************
8650 ****************************************************************************/
8651
8652 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8653 {
8654         uint32 level = q_u->level;
8655         RPC_BUFFER *buffer = NULL;
8656         uint32 offered = q_u->offered;
8657         uint32 *needed = &r_u->needed;
8658         uint32 *returned = &r_u->returned;
8659
8660         /* that's an [in out] buffer */
8661
8662         if (!q_u->buffer && (offered!=0)) {
8663                 return WERR_INVALID_PARAM;
8664         }
8665
8666         rpcbuf_move(q_u->buffer, &r_u->buffer);
8667         buffer = r_u->buffer;
8668
8669         DEBUG(5,("spoolss_enumprintmonitors\n"));
8670
8671         /*
8672          * Enumerate the print monitors ...
8673          *
8674          * Just reply with "Local Port", to keep NT happy
8675          * and I can use my nice printer checker.
8676          */
8677         
8678         *returned=0;
8679         *needed=0;
8680         
8681         switch (level) {
8682         case 1:
8683                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8684         case 2:
8685                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8686         default:
8687                 return WERR_UNKNOWN_LEVEL;
8688         }
8689 }
8690
8691 /****************************************************************************
8692 ****************************************************************************/
8693
8694 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8695                              NT_PRINTER_INFO_LEVEL *ntprinter,
8696                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered, 
8697                              uint32 *needed)
8698 {
8699         int i=0;
8700         BOOL found=False;
8701         JOB_INFO_1 *info_1=NULL;
8702         WERROR result = WERR_OK;
8703
8704         info_1=SMB_MALLOC_P(JOB_INFO_1);
8705
8706         if (info_1 == NULL) {
8707                 return WERR_NOMEM;
8708         }
8709                 
8710         for (i=0; i<count && found==False; i++) { 
8711                 if ((*queue)[i].job==(int)jobid)
8712                         found=True;
8713         }
8714         
8715         if (found==False) {
8716                 SAFE_FREE(info_1);
8717                 /* NT treats not found as bad param... yet another bad choice */
8718                 return WERR_INVALID_PARAM;
8719         }
8720         
8721         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8722         
8723         *needed += spoolss_size_job_info_1(info_1);
8724
8725         if (*needed > offered) {
8726                 result = WERR_INSUFFICIENT_BUFFER;
8727                 goto out;
8728         }
8729
8730         if (!rpcbuf_alloc_size(buffer, *needed)) {
8731                 result = WERR_NOMEM;
8732                 goto out;
8733         }
8734
8735         smb_io_job_info_1("", buffer, info_1, 0);
8736
8737 out:
8738         SAFE_FREE(info_1);
8739
8740         return result;
8741 }
8742
8743 /****************************************************************************
8744 ****************************************************************************/
8745
8746 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, 
8747                              NT_PRINTER_INFO_LEVEL *ntprinter,
8748                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered, 
8749                              uint32 *needed)
8750 {
8751         int             i = 0;
8752         BOOL            found = False;
8753         JOB_INFO_2      *info_2;
8754         WERROR          result;
8755         DEVICEMODE      *devmode = NULL;
8756         NT_DEVICEMODE   *nt_devmode = NULL;
8757
8758         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8759                 return WERR_NOMEM;
8760
8761         ZERO_STRUCTP(info_2);
8762
8763         for ( i=0; i<count && found==False; i++ ) 
8764         {
8765                 if ((*queue)[i].job == (int)jobid)
8766                         found = True;
8767         }
8768         
8769         if ( !found ) {
8770                 /* NT treats not found as bad param... yet another bad
8771                    choice */
8772                 result = WERR_INVALID_PARAM;
8773                 goto done;
8774         }
8775         
8776         /* 
8777          * if the print job does not have a DEVMODE associated with it, 
8778          * just use the one for the printer. A NULL devicemode is not
8779          *  a failure condition
8780          */
8781          
8782         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8783                 devmode = construct_dev_mode(snum);
8784         else {
8785                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8786                         ZERO_STRUCTP( devmode );
8787                         convert_nt_devicemode( devmode, nt_devmode );
8788                 }
8789         }
8790         
8791         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8792         
8793         *needed += spoolss_size_job_info_2(info_2);
8794
8795         if (*needed > offered) {
8796                 result = WERR_INSUFFICIENT_BUFFER;
8797                 goto done;
8798         }
8799
8800         if (!rpcbuf_alloc_size(buffer, *needed)) {
8801                 result = WERR_NOMEM;
8802                 goto done;
8803         }
8804
8805         smb_io_job_info_2("", buffer, info_2, 0);
8806
8807         result = WERR_OK;
8808         
8809  done:
8810         /* Cleanup allocated memory */
8811
8812         free_job_info_2(info_2);        /* Also frees devmode */
8813         SAFE_FREE(info_2);
8814
8815         return result;
8816 }
8817
8818 /****************************************************************************
8819 ****************************************************************************/
8820
8821 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8822 {
8823         POLICY_HND *handle = &q_u->handle;
8824         uint32 jobid = q_u->jobid;
8825         uint32 level = q_u->level;
8826         RPC_BUFFER *buffer = NULL;
8827         uint32 offered = q_u->offered;
8828         uint32 *needed = &r_u->needed;
8829         WERROR          wstatus = WERR_OK;
8830         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8831         int snum;
8832         int count;
8833         print_queue_struct      *queue = NULL;
8834         print_status_struct prt_status;
8835
8836         /* that's an [in out] buffer */
8837
8838         if (!q_u->buffer && (offered!=0)) {
8839                 return WERR_INVALID_PARAM;
8840         }
8841
8842         rpcbuf_move(q_u->buffer, &r_u->buffer);
8843         buffer = r_u->buffer;
8844
8845         DEBUG(5,("spoolss_getjob\n"));
8846         
8847         *needed = 0;
8848         
8849         if (!get_printer_snum(p, handle, &snum))
8850                 return WERR_BADFID;
8851         
8852         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8853         if ( !W_ERROR_IS_OK(wstatus) )
8854                 return wstatus;
8855                 
8856         count = print_queue_status(snum, &queue, &prt_status);
8857         
8858         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8859                      count, prt_status.status, prt_status.message));
8860                 
8861         switch ( level ) {
8862         case 1:
8863                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid, 
8864                                 buffer, offered, needed);
8865                         break;
8866         case 2:
8867                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid, 
8868                                 buffer, offered, needed);
8869                         break;
8870         default:
8871                         wstatus = WERR_UNKNOWN_LEVEL;
8872                         break;
8873         }
8874         
8875         SAFE_FREE(queue);
8876         free_a_printer( &ntprinter, 2 );
8877         
8878         return wstatus;
8879 }
8880
8881 /********************************************************************
8882  spoolss_getprinterdataex
8883  
8884  From MSDN documentation of GetPrinterDataEx: pass request
8885  to GetPrinterData if key is "PrinterDriverData".
8886  ********************************************************************/
8887
8888 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8889 {
8890         POLICY_HND      *handle = &q_u->handle;
8891         uint32          in_size = q_u->size;
8892         uint32          *type = &r_u->type;
8893         uint32          *out_size = &r_u->size;
8894         uint8           **data = &r_u->data;
8895         uint32          *needed = &r_u->needed;
8896         fstring         keyname, valuename;
8897         
8898         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8899         
8900         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8901         int                     snum = 0;
8902         WERROR                  status = WERR_OK;
8903
8904         DEBUG(4,("_spoolss_getprinterdataex\n"));
8905
8906         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8907         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8908         
8909         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
8910                 keyname, valuename));
8911
8912         /* in case of problem, return some default values */
8913         
8914         *needed   = 0;
8915         *type     = 0;
8916         *out_size = in_size;
8917
8918         if (!Printer) {
8919                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8920                 status = WERR_BADFID;
8921                 goto done;
8922         }
8923
8924         /* Is the handle to a printer or to the server? */
8925
8926         if (Printer->printer_type == SPLHND_SERVER) {
8927                 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8928                 status = WERR_INVALID_PARAM;
8929                 goto done;
8930         }
8931         
8932         if ( !get_printer_snum(p,handle, &snum) )
8933                 return WERR_BADFID;
8934
8935         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8936         if ( !W_ERROR_IS_OK(status) )
8937                 goto done;
8938
8939         /* check to see if the keyname is valid */
8940         if ( !strlen(keyname) ) {
8941                 status = WERR_INVALID_PARAM;
8942                 goto done;
8943         }
8944         
8945         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8946                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8947                 free_a_printer( &printer, 2 );
8948                 status = WERR_BADFILE;
8949                 goto done;
8950         }
8951         
8952         /* When given a new keyname, we should just create it */
8953
8954         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8955         
8956         if (*needed > *out_size)
8957                 status = WERR_MORE_DATA;
8958
8959 done:
8960         if ( !W_ERROR_IS_OK(status) ) 
8961         {
8962                 DEBUG(5, ("error: allocating %d\n", *out_size));
8963                 
8964                 /* reply this param doesn't exist */
8965                 
8966                 if ( *out_size ) 
8967                 {
8968                         if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8969                                 status = WERR_NOMEM;
8970                                 goto done;
8971                         }
8972                 } 
8973                 else {
8974                         *data = NULL;
8975         }
8976         }
8977         
8978         if ( printer )
8979         free_a_printer( &printer, 2 );
8980         
8981         return status;
8982 }
8983
8984 /********************************************************************
8985  * spoolss_setprinterdataex
8986  ********************************************************************/
8987
8988 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8989 {
8990         POLICY_HND              *handle = &q_u->handle; 
8991         uint32                  type = q_u->type;
8992         uint8                   *data = q_u->data;
8993         uint32                  real_len = q_u->real_len;
8994
8995         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8996         int                     snum = 0;
8997         WERROR                  status = WERR_OK;
8998         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
8999         fstring                 valuename;
9000         fstring                 keyname;
9001         char                    *oid_string;
9002         
9003         DEBUG(4,("_spoolss_setprinterdataex\n"));
9004
9005         /* From MSDN documentation of SetPrinterDataEx: pass request to
9006            SetPrinterData if key is "PrinterDriverData" */
9007
9008         if (!Printer) {
9009                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9010                 return WERR_BADFID;
9011         }
9012
9013         if ( Printer->printer_type == SPLHND_SERVER ) {
9014                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9015                 return WERR_INVALID_PARAM;
9016         }
9017
9018         if ( !get_printer_snum(p,handle, &snum) )
9019                 return WERR_BADFID;
9020
9021         /* 
9022          * Access check : NT returns "access denied" if you make a 
9023          * SetPrinterData call without the necessary privildge.
9024          * we were originally returning OK if nothing changed
9025          * which made Win2k issue **a lot** of SetPrinterData
9026          * when connecting to a printer  --jerry
9027          */
9028
9029         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
9030         {
9031                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9032                 return WERR_ACCESS_DENIED;
9033         }
9034
9035         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9036         if (!W_ERROR_IS_OK(status))
9037                 return status;
9038
9039         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9040         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9041         
9042         /* check for OID in valuename */
9043         
9044         if ( (oid_string = strchr( valuename, ',' )) != NULL )
9045         {
9046                 *oid_string = '\0';
9047                 oid_string++;
9048         }
9049
9050         /* save the registry data */
9051         
9052         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
9053         
9054         if ( W_ERROR_IS_OK(status) )
9055         {
9056                 /* save the OID if one was specified */
9057                 if ( oid_string ) {
9058                         fstrcat( keyname, "\\" );
9059                         fstrcat( keyname, SPOOL_OID_KEY );
9060                 
9061                         /* 
9062                          * I'm not checking the status here on purpose.  Don't know 
9063                          * if this is right, but I'm returning the status from the 
9064                          * previous set_printer_dataex() call.  I have no idea if 
9065                          * this is right.    --jerry
9066                          */
9067                  
9068                         set_printer_dataex( printer, keyname, valuename, 
9069                                             REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
9070                 }
9071         
9072                 status = mod_a_printer(printer, 2);
9073         }
9074                 
9075         free_a_printer(&printer, 2);
9076
9077         return status;
9078 }
9079
9080
9081 /********************************************************************
9082  * spoolss_deleteprinterdataex
9083  ********************************************************************/
9084
9085 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9086 {
9087         POLICY_HND      *handle = &q_u->handle;
9088         UNISTR2         *value = &q_u->valuename;
9089         UNISTR2         *key = &q_u->keyname;
9090
9091         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9092         int             snum=0;
9093         WERROR          status = WERR_OK;
9094         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9095         pstring         valuename, keyname;
9096         
9097         DEBUG(5,("spoolss_deleteprinterdataex\n"));
9098         
9099         if (!Printer) {
9100                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9101                 return WERR_BADFID;
9102         }
9103
9104         if (!get_printer_snum(p, handle, &snum))
9105                 return WERR_BADFID;
9106
9107         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9108                 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9109                 return WERR_ACCESS_DENIED;
9110         }
9111
9112         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9113         if (!W_ERROR_IS_OK(status))
9114                 return status;
9115
9116         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9117         unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9118
9119         status = delete_printer_dataex( printer, keyname, valuename );
9120
9121         if ( W_ERROR_IS_OK(status) )
9122                 mod_a_printer( printer, 2 );
9123                 
9124         free_a_printer(&printer, 2);
9125
9126         return status;
9127 }
9128
9129 /********************************************************************
9130  * spoolss_enumprinterkey
9131  ********************************************************************/
9132
9133
9134 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9135 {
9136         fstring         key;
9137         fstring         *keynames = NULL;
9138         uint16          *enumkeys = NULL;
9139         int             num_keys;
9140         int             printerkey_len;
9141         POLICY_HND      *handle = &q_u->handle;
9142         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9143         NT_PRINTER_DATA *data;
9144         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9145         int             snum = 0;
9146         WERROR          status = WERR_BADFILE;
9147         
9148         
9149         DEBUG(4,("_spoolss_enumprinterkey\n"));
9150
9151         if (!Printer) {
9152                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9153                 return WERR_BADFID;
9154         }
9155
9156         if ( !get_printer_snum(p,handle, &snum) )
9157                 return WERR_BADFID;
9158
9159         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9160         if (!W_ERROR_IS_OK(status))
9161                 return status;
9162                 
9163         /* get the list of subkey names */
9164         
9165         unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9166         data = printer->info_2->data;
9167
9168         num_keys = get_printer_subkeys( data, key, &keynames );
9169
9170         if ( num_keys == -1 ) {
9171                 status = WERR_BADFILE;
9172                 goto done;
9173         }
9174
9175         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9176
9177         r_u->needed = printerkey_len*2;
9178
9179         if ( q_u->size < r_u->needed ) {
9180                 status = WERR_MORE_DATA;
9181                 goto done;
9182         }
9183
9184         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9185                 status = WERR_NOMEM;
9186                 goto done;
9187         }
9188                         
9189         status = WERR_OK;
9190
9191         if ( q_u->size < r_u->needed ) 
9192                 status = WERR_MORE_DATA;
9193
9194 done:
9195         free_a_printer( &printer, 2 );
9196         SAFE_FREE( keynames );
9197         
9198         return status;
9199 }
9200
9201 /********************************************************************
9202  * spoolss_deleteprinterkey
9203  ********************************************************************/
9204
9205 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9206 {
9207         POLICY_HND              *handle = &q_u->handle;
9208         Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9209         fstring                 key;
9210         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9211         int                     snum=0;
9212         WERROR                  status;
9213         
9214         DEBUG(5,("spoolss_deleteprinterkey\n"));
9215         
9216         if (!Printer) {
9217                 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9218                 return WERR_BADFID;
9219         }
9220
9221         /* if keyname == NULL, return error */
9222         
9223         if ( !q_u->keyname.buffer )
9224                 return WERR_INVALID_PARAM;
9225                 
9226         if (!get_printer_snum(p, handle, &snum))
9227                 return WERR_BADFID;
9228
9229         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9230                 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9231                 return WERR_ACCESS_DENIED;
9232         }
9233
9234         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9235         if (!W_ERROR_IS_OK(status))
9236                 return status;
9237         
9238         /* delete the key and all subneys */
9239         
9240         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9241  
9242         status = delete_all_printer_data( printer->info_2, key );       
9243
9244         if ( W_ERROR_IS_OK(status) )
9245                 status = mod_a_printer(printer, 2);
9246         
9247         free_a_printer( &printer, 2 );
9248         
9249         return status;
9250 }
9251
9252
9253 /********************************************************************
9254  * spoolss_enumprinterdataex
9255  ********************************************************************/
9256
9257 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9258 {
9259         POLICY_HND      *handle = &q_u->handle; 
9260         uint32          in_size = q_u->size;
9261         uint32          num_entries, 
9262                         needed;
9263         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9264         PRINTER_ENUM_VALUES     *enum_values = NULL;
9265         NT_PRINTER_DATA         *p_data;
9266         fstring         key;
9267         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9268         int             snum;
9269         WERROR          result;
9270         int             key_index;
9271         int             i;
9272         REGISTRY_VALUE  *val;
9273         char            *value_name;
9274         uint32          data_len;
9275         
9276
9277         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9278
9279         if (!Printer) {
9280                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9281                 return WERR_BADFID;
9282         }
9283
9284         /* 
9285          * first check for a keyname of NULL or "".  Win2k seems to send 
9286          * this a lot and we should send back WERR_INVALID_PARAM
9287          * no need to spend time looking up the printer in this case.
9288          * --jerry
9289          */
9290          
9291         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9292         if ( !strlen(key) ) {
9293                 result = WERR_INVALID_PARAM;
9294                 goto done;
9295         }
9296
9297         /* get the printer off of disk */
9298         
9299         if (!get_printer_snum(p,handle, &snum))
9300                 return WERR_BADFID;
9301         
9302         ZERO_STRUCT(printer);
9303         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9304         if (!W_ERROR_IS_OK(result))
9305                 return result;
9306         
9307         /* now look for a match on the key name */
9308         
9309         p_data = printer->info_2->data;
9310         
9311         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9312         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9313         {
9314                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9315                 result = WERR_INVALID_PARAM;
9316                 goto done;
9317         }
9318         
9319         result = WERR_OK;
9320         needed = 0;
9321         
9322         /* allocate the memory for the array of pointers -- if necessary */
9323         
9324         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9325         if ( num_entries )
9326         {
9327                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9328                 {
9329                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9330                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9331                         result = WERR_NOMEM;
9332                         goto done;
9333                 }
9334
9335                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9336         }
9337                 
9338         /* 
9339          * loop through all params and build the array to pass 
9340          * back to the  client 
9341          */
9342          
9343         for ( i=0; i<num_entries; i++ )
9344         {
9345                 /* lookup the registry value */
9346                 
9347                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9348                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9349
9350                 /* copy the data */
9351                 
9352                 value_name = regval_name( val );
9353                 init_unistr( &enum_values[i].valuename, value_name );
9354                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9355                 enum_values[i].type      = regval_type( val );
9356                 
9357                 data_len = regval_size( val );
9358                 if ( data_len ) {
9359                         if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) ) 
9360                         {
9361                                 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", 
9362                                         data_len ));
9363                                 result = WERR_NOMEM;
9364                                 goto done;
9365                         }
9366                 }
9367                 enum_values[i].data_len = data_len;
9368
9369                 /* keep track of the size of the array in bytes */
9370                 
9371                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9372         }
9373         
9374         /* housekeeping information in the reply */
9375         
9376         r_u->needed     = needed;
9377         r_u->returned   = num_entries;
9378
9379         if (needed > in_size) {
9380                 result = WERR_MORE_DATA;
9381                 goto done;
9382         }
9383                 
9384         /* copy data into the reply */
9385         
9386         r_u->ctr.size           = r_u->needed;
9387         r_u->ctr.size_of_array  = r_u->returned;
9388         r_u->ctr.values         = enum_values;
9389         
9390         
9391                 
9392 done:   
9393         if ( printer )
9394         free_a_printer(&printer, 2);
9395
9396         return result;
9397 }
9398
9399 /****************************************************************************
9400 ****************************************************************************/
9401
9402 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9403 {
9404         init_unistr(&info->name, name);
9405 }
9406
9407 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
9408                                                  UNISTR2 *environment, 
9409                                                  RPC_BUFFER *buffer, 
9410                                                  uint32 offered, 
9411                                                  uint32 *needed)
9412 {
9413         pstring path;
9414         pstring long_archi;
9415         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9416         WERROR result = WERR_OK;
9417
9418         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9419
9420         if (!get_short_archi(long_archi))
9421                 return WERR_INVALID_ENVIRONMENT;
9422
9423         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9424                 return WERR_NOMEM;
9425
9426         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9427
9428         fill_printprocessordirectory_1(info, path);
9429         
9430         *needed += spoolss_size_printprocessordirectory_info_1(info);
9431
9432         if (*needed > offered) {
9433                 result = WERR_INSUFFICIENT_BUFFER;
9434                 goto out;
9435         }
9436
9437         if (!rpcbuf_alloc_size(buffer, *needed)) {
9438                 result = WERR_INSUFFICIENT_BUFFER;
9439                 goto out;
9440         }
9441
9442         smb_io_printprocessordirectory_1("", buffer, info, 0);
9443
9444 out:
9445         SAFE_FREE(info);
9446         
9447         return result;
9448 }
9449
9450 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9451 {
9452         uint32 level = q_u->level;
9453         RPC_BUFFER *buffer = NULL;
9454         uint32 offered = q_u->offered;
9455         uint32 *needed = &r_u->needed;
9456         WERROR result;
9457
9458         /* that's an [in out] buffer */
9459
9460         if (!q_u->buffer && (offered!=0)) {
9461                 return WERR_INVALID_PARAM;
9462         }
9463
9464         rpcbuf_move(q_u->buffer, &r_u->buffer);
9465         buffer = r_u->buffer;
9466
9467         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9468         
9469         *needed=0;
9470
9471         switch(level) {
9472         case 1:
9473                 result = getprintprocessordirectory_level_1
9474                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9475                 break;
9476         default:
9477                 result = WERR_UNKNOWN_LEVEL;
9478         }
9479
9480         return result;
9481 }
9482
9483 /*******************************************************************
9484  Streams the monitor UI DLL name in UNICODE
9485 *******************************************************************/
9486
9487 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, 
9488                                 RPC_BUFFER *out, uint32 *needed )
9489 {
9490         const char *dllname = "tcpmonui.dll";
9491         
9492         *needed = (strlen(dllname)+1) * 2;
9493         
9494         if ( rpcbuf_get_size(out) < *needed ) {
9495                 return WERR_INSUFFICIENT_BUFFER;                
9496         }
9497         
9498         if ( !make_monitorui_buf( out, dllname ) ) {
9499                 return WERR_NOMEM;
9500         }
9501         
9502         return WERR_OK;
9503 }
9504
9505 /*******************************************************************
9506  Create a new TCP/IP port
9507 *******************************************************************/
9508
9509 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in, 
9510                               RPC_BUFFER *out, uint32 *needed )
9511 {
9512         NT_PORT_DATA_1 port1;
9513         pstring device_uri;
9514
9515         ZERO_STRUCT( port1 );
9516
9517         /* convert to our internal port data structure */
9518
9519         if ( !convert_port_data_1( &port1, in ) ) {
9520                 return WERR_NOMEM;
9521         }
9522
9523         /* create the device URI and call the add_port_hook() */
9524
9525         switch ( port1.protocol ) {
9526         case PORT_PROTOCOL_DIRECT:
9527                 pstr_sprintf( device_uri, "socket://%s:%d/", port1.hostaddr, port1.port );
9528                 break;
9529
9530         case PORT_PROTOCOL_LPR:
9531                 pstr_sprintf( device_uri, "lpr://%s/%s", port1.hostaddr, port1.queue );
9532                 break;
9533         
9534         default:
9535                 return WERR_UNKNOWN_PORT;
9536         }
9537
9538         return add_port_hook( token, port1.name, device_uri );
9539 }
9540
9541 /*******************************************************************
9542 *******************************************************************/
9543
9544 struct xcv_api_table xcvtcp_cmds[] = {
9545         { "MonitorUI",  xcvtcp_monitorui },
9546         { "AddPort",    xcvtcp_addport},
9547         { NULL,         NULL }
9548 };
9549
9550 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command, 
9551                                       RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, 
9552                                       uint32 *needed )
9553 {
9554         int i;
9555         
9556         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9557         
9558         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9559                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9560                         return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9561         }
9562         
9563         return WERR_BADFUNC;
9564 }
9565
9566 /*******************************************************************
9567 *******************************************************************/
9568 #if 0   /* don't support management using the "Local Port" monitor */
9569
9570 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in, 
9571                                   RPC_BUFFER *out, uint32 *needed )
9572 {
9573         const char *dllname = "localui.dll";
9574         
9575         *needed = (strlen(dllname)+1) * 2;
9576         
9577         if ( rpcbuf_get_size(out) < *needed ) {
9578                 return WERR_INSUFFICIENT_BUFFER;                
9579         }
9580         
9581         if ( !make_monitorui_buf( out, dllname )) {
9582                 return WERR_NOMEM;
9583         }
9584         
9585         return WERR_OK;
9586 }
9587
9588 /*******************************************************************
9589 *******************************************************************/
9590
9591 struct xcv_api_table xcvlocal_cmds[] = {
9592         { "MonitorUI",  xcvlocal_monitorui },
9593         { NULL,         NULL }
9594 };
9595 #else
9596 struct xcv_api_table xcvlocal_cmds[] = {
9597         { NULL,         NULL }
9598 };
9599 #endif
9600
9601
9602
9603 /*******************************************************************
9604 *******************************************************************/
9605
9606 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command, 
9607                                         RPC_BUFFER *inbuf, RPC_BUFFER *outbuf, 
9608                                         uint32 *needed )
9609 {
9610         int i;
9611         
9612         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9613
9614         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9615                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9616                         return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9617         }
9618         return WERR_BADFUNC;
9619 }
9620
9621 /*******************************************************************
9622 *******************************************************************/
9623
9624 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9625 {       
9626         Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9627         fstring command;
9628
9629         if (!Printer) {
9630                 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9631                 return WERR_BADFID;
9632         }
9633
9634         /* Has to be a handle to the TCP/IP port monitor */
9635         
9636         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9637                 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9638                 return WERR_BADFID;
9639         }
9640         
9641         /* requires administrative access to the server */
9642         
9643         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9644                 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9645                 return WERR_ACCESS_DENIED;
9646         }
9647
9648         /* Get the command name.  There's numerous commands supported by the 
9649            TCPMON interface. */
9650         
9651         rpcstr_pull(command, q_u->dataname.buffer, sizeof(command), 
9652                 q_u->dataname.uni_str_len*2, 0);
9653                 
9654         /* Allocate the outgoing buffer */
9655         
9656         rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9657         
9658         switch ( Printer->printer_type ) {
9659         case SPLHND_PORTMON_TCP:
9660                 return process_xcvtcp_command( p->pipe_user.nt_user_token, command, 
9661                         &q_u->indata, &r_u->outdata, &r_u->needed );
9662         case SPLHND_PORTMON_LOCAL:
9663                 return process_xcvlocal_command( p->pipe_user.nt_user_token, command, 
9664                         &q_u->indata, &r_u->outdata, &r_u->needed );
9665         }
9666
9667         return WERR_INVALID_PRINT_MONITOR;
9668 }
9669
9670