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