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