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