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