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