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