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