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