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