r4184: Removed unused extern.
[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         WERROR result;
5851         int snum;
5852
5853         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5854
5855         if (!Printer || !get_printer_snum(p, handle, &snum)) {
5856                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5857                          OUR_HANDLE(handle)));
5858
5859                 result = WERR_BADFID;
5860                 goto done;
5861         }
5862         
5863         /* Check the user has permissions to change the security
5864            descriptor.  By experimentation with two NT machines, the user
5865            requires Full Access to the printer to change security
5866            information. */
5867
5868         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5869                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5870                 result = WERR_ACCESS_DENIED;
5871                 goto done;
5872         }
5873
5874         /* NT seems to like setting the security descriptor even though
5875            nothing may have actually changed. */
5876
5877         nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5878
5879         if (DEBUGLEVEL >= 10) {
5880                 SEC_ACL *the_acl;
5881                 int i;
5882
5883                 the_acl = old_secdesc_ctr->sec->dacl;
5884                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
5885                            PRINTERNAME(snum), the_acl->num_aces));
5886
5887                 for (i = 0; i < the_acl->num_aces; i++) {
5888                         fstring sid_str;
5889
5890                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5891
5892                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
5893                                   the_acl->ace[i].info.mask));
5894                 }
5895
5896                 the_acl = secdesc_ctr->sec->dacl;
5897
5898                 if (the_acl) {
5899                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5900                                    PRINTERNAME(snum), the_acl->num_aces));
5901
5902                         for (i = 0; i < the_acl->num_aces; i++) {
5903                                 fstring sid_str;
5904                                 
5905                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5906                                 
5907                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
5908                                            the_acl->ace[i].info.mask));
5909                         }
5910                 } else {
5911                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5912                 }
5913         }
5914
5915         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5916
5917         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5918                 result = WERR_OK;
5919                 goto done;
5920         }
5921
5922         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5923
5924  done:
5925
5926         return result;
5927 }
5928
5929 /********************************************************************
5930  Canonicalize printer info from a client
5931
5932  ATTN: It does not matter what we set the servername to hear 
5933  since we do the necessary work in get_a_printer() to set it to 
5934  the correct value based on what the client sent in the 
5935  _spoolss_open_printer_ex().
5936  ********************************************************************/
5937
5938 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5939 {
5940         fstring printername;
5941         const char *p;
5942         
5943         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5944                 "portname=%s drivername=%s comment=%s location=%s\n",
5945                 info->servername, info->printername, info->sharename, 
5946                 info->portname, info->drivername, info->comment, info->location));
5947
5948         /* we force some elements to "correct" values */
5949         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5950         fstrcpy(info->sharename, lp_servicename(snum));
5951         
5952         /* check to see if we allow printername != sharename */
5953
5954         if ( lp_force_printername(snum) ) {
5955                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5956                         global_myname(), info->sharename );
5957         } else {
5958
5959                 /* make sure printername is in \\server\printername format */
5960         
5961                 fstrcpy( printername, info->printername );
5962                 p = printername;
5963                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5964                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5965                                 p++;
5966                 }
5967                 
5968                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5969                          global_myname(), p );
5970         }
5971
5972         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5973         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5974         
5975         
5976         
5977         return True;
5978 }
5979
5980 /****************************************************************************
5981 ****************************************************************************/
5982
5983 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5984 {
5985         extern userdom_struct current_user_info;
5986         char *cmd = lp_addprinter_cmd();
5987         char **qlines;
5988         pstring command;
5989         int numlines;
5990         int ret;
5991         int fd;
5992         fstring remote_machine = "%m";
5993
5994         standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5995         
5996         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5997                         cmd, printer->info_2->printername, printer->info_2->sharename,
5998                         printer->info_2->portname, printer->info_2->drivername,
5999                         printer->info_2->location, printer->info_2->comment, remote_machine);
6000
6001         DEBUG(10,("Running [%s]\n", command));
6002         ret = smbrun(command, &fd);
6003         DEBUGADD(10,("returned [%d]\n", ret));
6004
6005         if ( ret != 0 ) {
6006                 if (fd != -1)
6007                         close(fd);
6008                 return False;
6009         }
6010
6011         numlines = 0;
6012         /* Get lines and convert them back to dos-codepage */
6013         qlines = fd_lines_load(fd, &numlines);
6014         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6015         close(fd);
6016
6017         if(numlines) {
6018                 /* Set the portname to what the script says the portname should be. */
6019                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6020                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6021
6022                 /* Send SIGHUP to process group... is there a better way? */
6023                 kill(0, SIGHUP);
6024                 
6025                 /* reload our services immediately */
6026                 reload_services( False );
6027         }
6028
6029         file_lines_free(qlines);
6030         return True;
6031 }
6032
6033 /********************************************************************
6034  * Called by spoolss_api_setprinter
6035  * when updating a printer description.
6036  ********************************************************************/
6037
6038 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6039                            const SPOOL_PRINTER_INFO_LEVEL *info,
6040                            DEVICEMODE *devmode)
6041 {
6042         int snum;
6043         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6044         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6045         WERROR result;
6046         UNISTR2 buffer;
6047         fstring asc_buffer;
6048
6049         DEBUG(8,("update_printer\n"));
6050
6051         result = WERR_OK;
6052
6053         if (!Printer) {
6054                 result = WERR_BADFID;
6055                 goto done;
6056         }
6057
6058         if (!get_printer_snum(p, handle, &snum)) {
6059                 result = WERR_BADFID;
6060                 goto done;
6061         }
6062
6063         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6064             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6065                 result = WERR_BADFID;
6066                 goto done;
6067         }
6068
6069         DEBUGADD(8,("Converting info_2 struct\n"));
6070
6071         /*
6072          * convert_printer_info converts the incoming
6073          * info from the client and overwrites the info
6074          * just read from the tdb in the pointer 'printer'.
6075          */
6076
6077         if (!convert_printer_info(info, printer, level)) {
6078                 result =  WERR_NOMEM;
6079                 goto done;
6080         }
6081
6082         if (devmode) {
6083                 /* we have a valid devmode
6084                    convert it and link it*/
6085
6086                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6087                 if (!convert_devicemode(printer->info_2->printername, devmode,
6088                                 &printer->info_2->devmode)) {
6089                         result =  WERR_NOMEM;
6090                         goto done;
6091                 }
6092         }
6093
6094         /* Do sanity check on the requested changes for Samba */
6095
6096         if (!check_printer_ok(printer->info_2, snum)) {
6097                 result = WERR_INVALID_PARAM;
6098                 goto done;
6099         }
6100
6101         /* FIXME!!! If the driver has changed we really should verify that 
6102            it is installed before doing much else   --jerry */
6103
6104         /* Check calling user has permission to update printer description */
6105
6106         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6107                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6108                 result = WERR_ACCESS_DENIED;
6109                 goto done;
6110         }
6111
6112         /* Call addprinter hook */
6113         /* Check changes to see if this is really needed */
6114         
6115         if ( *lp_addprinter_cmd() 
6116                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6117                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6118                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6119                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6120         {
6121                 if ( !add_printer_hook(printer) ) {
6122                         result = WERR_ACCESS_DENIED;
6123                         goto done;
6124                 }
6125
6126                 /* 
6127                  * make sure we actually reload the services after 
6128                  * this as smb.conf could have a new section in it 
6129                  * .... shouldn't .... but could
6130                  */
6131                 reload_services(False); 
6132         }
6133         
6134         /*
6135          * When a *new* driver is bound to a printer, the drivername is used to
6136          * lookup previously saved driver initialization info, which is then
6137          * bound to the printer, simulating what happens in the Windows arch.
6138          */
6139         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6140         {
6141                 if (!set_driver_init(printer, 2)) 
6142                 {
6143                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6144                                 printer->info_2->drivername));
6145                 }
6146                 
6147                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6148                         printer->info_2->drivername));
6149                         
6150                 notify_printer_driver(snum, printer->info_2->drivername);
6151         }
6152
6153         /* 
6154          * flag which changes actually occured.  This is a small subset of 
6155          * all the possible changes.  We also have to update things in the 
6156          * DsSpooler key.
6157          */
6158
6159         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6160                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6161                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6162                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6163
6164                 notify_printer_comment(snum, printer->info_2->comment);
6165         }
6166
6167         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6168                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6169                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6170                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6171
6172                 notify_printer_sharename(snum, printer->info_2->sharename);
6173         }
6174
6175         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6176                 char *pname;
6177                 
6178                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6179                         pname++;
6180                 else
6181                         pname = printer->info_2->printername;
6182                         
6183
6184                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6185                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6186                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6187
6188                 notify_printer_printername( snum, pname );
6189         }
6190         
6191         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6192                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6193                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6194                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6195
6196                 notify_printer_port(snum, printer->info_2->portname);
6197         }
6198
6199         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6200                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6201                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6202                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6203
6204                 notify_printer_location(snum, printer->info_2->location);
6205         }
6206         
6207         /* here we need to update some more DsSpooler keys */
6208         /* uNCName, serverName, shortServerName */
6209         
6210         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6211         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6212                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6213         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6214                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6215
6216         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6217                  global_myname(), printer->info_2->sharename );
6218         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6219         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6220                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6221
6222         /* Update printer info */
6223         result = mod_a_printer(printer, 2);
6224
6225 done:
6226         free_a_printer(&printer, 2);
6227         free_a_printer(&old_printer, 2);
6228
6229
6230         return result;
6231 }
6232
6233 /****************************************************************************
6234 ****************************************************************************/
6235 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6236                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6237 {
6238 #ifdef HAVE_ADS
6239         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6240         int snum;
6241         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6242
6243         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6244
6245         if (!Printer)
6246                 return WERR_BADFID;
6247
6248         if (!get_printer_snum(p, handle, &snum))
6249                 return WERR_BADFID;
6250         
6251         nt_printer_publish(Printer, snum, info7->action);
6252         
6253         return WERR_OK;
6254 #else
6255         return WERR_UNKNOWN_LEVEL;
6256 #endif
6257 }
6258 /****************************************************************************
6259 ****************************************************************************/
6260
6261 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6262 {
6263         POLICY_HND *handle = &q_u->handle;
6264         uint32 level = q_u->level;
6265         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6266         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6267         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6268         uint32 command = q_u->command;
6269         WERROR result;
6270
6271         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6272         
6273         if (!Printer) {
6274                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6275                 return WERR_BADFID;
6276         }
6277
6278         /* check the level */   
6279         switch (level) {
6280                 case 0:
6281                         return control_printer(handle, command, p);
6282                 case 2:
6283                         result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6284                         if (!W_ERROR_IS_OK(result)) 
6285                                 return result;
6286                         if (secdesc_ctr)
6287                                 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6288                         return result;
6289                 case 3:
6290                         return update_printer_sec(handle, level, info, p,
6291                                                   secdesc_ctr);
6292                 case 7:
6293                         return publish_or_unpublish_printer(p, handle, info);
6294                 default:
6295                         return WERR_UNKNOWN_LEVEL;
6296         }
6297 }
6298
6299 /****************************************************************************
6300 ****************************************************************************/
6301
6302 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6303 {
6304         POLICY_HND *handle = &q_u->handle;
6305         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6306         
6307         if (!Printer) {
6308                 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6309                 return WERR_BADFID;
6310         }
6311
6312         if (Printer->notify.client_connected==True) {
6313                 int snum = -1;
6314
6315                 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6316                         snum = -1;
6317                 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6318                                 !get_printer_snum(p, handle, &snum) )
6319                         return WERR_BADFID;
6320
6321                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6322         }
6323
6324         Printer->notify.flags=0;
6325         Printer->notify.options=0;
6326         Printer->notify.localmachine[0]='\0';
6327         Printer->notify.printerlocal=0;
6328         if (Printer->notify.option)
6329                 free_spool_notify_option(&Printer->notify.option);
6330         Printer->notify.client_connected=False;
6331
6332         return WERR_OK;
6333 }
6334
6335 /****************************************************************************
6336 ****************************************************************************/
6337
6338 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6339 {
6340         /* that's an [in out] buffer (despite appearences to the contrary) */
6341         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6342
6343         r_u->needed = 0;
6344         return WERR_INVALID_PARAM; /* this is what a NT server
6345                                            returns for AddJob. AddJob
6346                                            must fail on non-local
6347                                            printers */
6348 }
6349
6350 /****************************************************************************
6351 ****************************************************************************/
6352
6353 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6354                             int position, int snum, 
6355                             NT_PRINTER_INFO_LEVEL *ntprinter)
6356 {
6357         struct tm *t;
6358         
6359         t=gmtime(&queue->time);
6360
6361         job_info->jobid=queue->job;     
6362         init_unistr(&job_info->printername, lp_servicename(snum));
6363         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6364         init_unistr(&job_info->username, queue->fs_user);
6365         init_unistr(&job_info->document, queue->fs_file);
6366         init_unistr(&job_info->datatype, "RAW");
6367         init_unistr(&job_info->text_status, "");
6368         job_info->status=nt_printj_status(queue->status);
6369         job_info->priority=queue->priority;
6370         job_info->position=position;
6371         job_info->totalpages=queue->page_count;
6372         job_info->pagesprinted=0;
6373
6374         make_systemtime(&job_info->submitted, t);
6375 }
6376
6377 /****************************************************************************
6378 ****************************************************************************/
6379
6380 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6381                             int position, int snum, 
6382                             NT_PRINTER_INFO_LEVEL *ntprinter,
6383                             DEVICEMODE *devmode)
6384 {
6385         struct tm *t;
6386
6387         t=gmtime(&queue->time);
6388
6389         job_info->jobid=queue->job;
6390         
6391         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6392         
6393         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6394         init_unistr(&job_info->username, queue->fs_user);
6395         init_unistr(&job_info->document, queue->fs_file);
6396         init_unistr(&job_info->notifyname, queue->fs_user);
6397         init_unistr(&job_info->datatype, "RAW");
6398         init_unistr(&job_info->printprocessor, "winprint");
6399         init_unistr(&job_info->parameters, "");
6400         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6401         init_unistr(&job_info->text_status, "");
6402         
6403 /* and here the security descriptor */
6404
6405         job_info->status=nt_printj_status(queue->status);
6406         job_info->priority=queue->priority;
6407         job_info->position=position;
6408         job_info->starttime=0;
6409         job_info->untiltime=0;
6410         job_info->totalpages=queue->page_count;
6411         job_info->size=queue->size;
6412         make_systemtime(&(job_info->submitted), t);
6413         job_info->timeelapsed=0;
6414         job_info->pagesprinted=0;
6415
6416         job_info->devmode = devmode;
6417
6418         return (True);
6419 }
6420
6421 /****************************************************************************
6422  Enumjobs at level 1.
6423 ****************************************************************************/
6424
6425 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6426                               NT_PRINTER_INFO_LEVEL *ntprinter,
6427                               NEW_BUFFER *buffer, uint32 offered,
6428                               uint32 *needed, uint32 *returned)
6429 {
6430         JOB_INFO_1 *info;
6431         int i;
6432         
6433         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6434         if (info==NULL) {
6435                 SAFE_FREE(queue);
6436                 *returned=0;
6437                 return WERR_NOMEM;
6438         }
6439         
6440         for (i=0; i<*returned; i++)
6441                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6442
6443         SAFE_FREE(queue);
6444
6445         /* check the required size. */  
6446         for (i=0; i<*returned; i++)
6447                 (*needed) += spoolss_size_job_info_1(&info[i]);
6448
6449         if (!alloc_buffer_size(buffer, *needed)) {
6450                 SAFE_FREE(info);
6451                 return WERR_INSUFFICIENT_BUFFER;
6452         }
6453
6454         /* fill the buffer with the structures */
6455         for (i=0; i<*returned; i++)
6456                 smb_io_job_info_1("", buffer, &info[i], 0);     
6457
6458         /* clear memory */
6459         SAFE_FREE(info);
6460
6461         if (*needed > offered) {
6462                 *returned=0;
6463                 return WERR_INSUFFICIENT_BUFFER;
6464         }
6465
6466         return WERR_OK;
6467 }
6468
6469 /****************************************************************************
6470  Enumjobs at level 2.
6471 ****************************************************************************/
6472
6473 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6474                               NT_PRINTER_INFO_LEVEL *ntprinter,
6475                               NEW_BUFFER *buffer, uint32 offered,
6476                               uint32 *needed, uint32 *returned)
6477 {
6478         JOB_INFO_2 *info = NULL;
6479         int i;
6480         WERROR result;
6481         DEVICEMODE *devmode = NULL;
6482         
6483         info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned);
6484         if (info==NULL) {
6485                 *returned=0;
6486                 result = WERR_NOMEM;
6487                 goto done;
6488         }
6489                 
6490         /* this should not be a failure condition if the devmode is NULL */
6491         
6492         devmode = construct_dev_mode(snum);
6493
6494         for (i=0; i<*returned; i++)
6495                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6496                                 devmode);
6497
6498         free_a_printer(&ntprinter, 2);
6499         SAFE_FREE(queue);
6500
6501         /* check the required size. */  
6502         for (i=0; i<*returned; i++)
6503                 (*needed) += spoolss_size_job_info_2(&info[i]);
6504
6505         if (*needed > offered) {
6506                 *returned=0;
6507                 result = WERR_INSUFFICIENT_BUFFER;
6508                 goto done;
6509         }
6510
6511         if (!alloc_buffer_size(buffer, *needed)) {
6512                 SAFE_FREE(info);
6513                 result = WERR_INSUFFICIENT_BUFFER;
6514                 goto done;
6515         }
6516
6517         /* fill the buffer with the structures */
6518         for (i=0; i<*returned; i++)
6519                 smb_io_job_info_2("", buffer, &info[i], 0);     
6520
6521         result = WERR_OK;
6522
6523  done:
6524         free_a_printer(&ntprinter, 2);
6525         free_devmode(devmode);
6526         SAFE_FREE(queue);
6527         SAFE_FREE(info);
6528
6529         return result;
6530
6531 }
6532
6533 /****************************************************************************
6534  Enumjobs.
6535 ****************************************************************************/
6536
6537 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6538 {       
6539         POLICY_HND *handle = &q_u->handle;
6540         uint32 level = q_u->level;
6541         NEW_BUFFER *buffer = NULL;
6542         uint32 offered = q_u->offered;
6543         uint32 *needed = &r_u->needed;
6544         uint32 *returned = &r_u->returned;
6545         WERROR wret;
6546         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6547         int snum;
6548         print_status_struct prt_status;
6549         print_queue_struct *queue=NULL;
6550
6551         /* that's an [in out] buffer */
6552         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6553         buffer = r_u->buffer;
6554
6555         DEBUG(4,("_spoolss_enumjobs\n"));
6556
6557         *needed=0;
6558         *returned=0;
6559
6560         /* lookup the printer snum and tdb entry */
6561         
6562         if (!get_printer_snum(p, handle, &snum))
6563                 return WERR_BADFID;
6564
6565         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6566         if ( !W_ERROR_IS_OK(wret) )
6567                 return wret;
6568         
6569         *returned = print_queue_status(snum, &queue, &prt_status);
6570         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6571
6572         if (*returned == 0) {
6573                 SAFE_FREE(queue);
6574                 return WERR_OK;
6575         }
6576
6577         switch (level) {
6578         case 1:
6579                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6580                 return wret;
6581         case 2:
6582                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6583                 return wret;
6584         default:
6585                 SAFE_FREE(queue);
6586                 *returned=0;
6587                 wret = WERR_UNKNOWN_LEVEL;
6588         }
6589         
6590         free_a_printer( &ntprinter, 2 );
6591         return wret;
6592 }
6593
6594 /****************************************************************************
6595 ****************************************************************************/
6596
6597 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6598 {
6599         return WERR_OK;
6600 }
6601
6602 /****************************************************************************
6603 ****************************************************************************/
6604
6605 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6606 {
6607         POLICY_HND *handle = &q_u->handle;
6608         uint32 jobid = q_u->jobid;
6609         uint32 command = q_u->command;
6610
6611         struct current_user user;
6612         int snum;
6613         WERROR errcode = WERR_BADFUNC;
6614                 
6615         if (!get_printer_snum(p, handle, &snum)) {
6616                 return WERR_BADFID;
6617         }
6618
6619         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6620                 return WERR_INVALID_PRINTER_NAME;
6621         }
6622
6623         get_current_user(&user, p);     
6624
6625         switch (command) {
6626         case JOB_CONTROL_CANCEL:
6627         case JOB_CONTROL_DELETE:
6628                 if (print_job_delete(&user, snum, jobid, &errcode)) {
6629                         errcode = WERR_OK;
6630                 }
6631                 break;
6632         case JOB_CONTROL_PAUSE:
6633                 if (print_job_pause(&user, snum, jobid, &errcode)) {
6634                         errcode = WERR_OK;
6635                 }               
6636                 break;
6637         case JOB_CONTROL_RESTART:
6638         case JOB_CONTROL_RESUME:
6639                 if (print_job_resume(&user, snum, jobid, &errcode)) {
6640                         errcode = WERR_OK;
6641                 }
6642                 break;
6643         default:
6644                 return WERR_UNKNOWN_LEVEL;
6645         }
6646
6647         return errcode;
6648 }
6649
6650 /****************************************************************************
6651  Enumerates all printer drivers at level 1.
6652 ****************************************************************************/
6653
6654 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6655 {
6656         int i;
6657         int ndrivers;
6658         uint32 version;
6659         fstring *list = NULL;
6660
6661         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6662         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6663
6664         *returned=0;
6665
6666         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6667                 list=NULL;
6668                 ndrivers=get_ntdrivers(&list, architecture, version);
6669                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6670
6671                 if(ndrivers == -1)
6672                         return WERR_NOMEM;
6673
6674                 if(ndrivers != 0) {
6675                         if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6676                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6677                                 SAFE_FREE(driver_info_1);
6678                                 SAFE_FREE(list);
6679                                 return WERR_NOMEM;
6680                         }
6681                         else driver_info_1 = tdi1;
6682                 }
6683
6684                 for (i=0; i<ndrivers; i++) {
6685                         WERROR status;
6686                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6687                         ZERO_STRUCT(driver);
6688                         status = get_a_printer_driver(&driver, 3, list[i], 
6689                                                       architecture, version);
6690                         if (!W_ERROR_IS_OK(status)) {
6691                                 SAFE_FREE(list);
6692                                 return status;
6693                         }
6694                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
6695                         free_a_printer_driver(driver, 3);
6696                 }       
6697
6698                 *returned+=ndrivers;
6699                 SAFE_FREE(list);
6700         }
6701         
6702         /* check the required size. */
6703         for (i=0; i<*returned; i++) {
6704                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6705                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6706         }
6707
6708         if (!alloc_buffer_size(buffer, *needed)) {
6709                 SAFE_FREE(driver_info_1);
6710                 return WERR_INSUFFICIENT_BUFFER;
6711         }
6712
6713         /* fill the buffer with the driver structures */
6714         for (i=0; i<*returned; i++) {
6715                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6716                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6717         }
6718
6719         SAFE_FREE(driver_info_1);
6720
6721         if (*needed > offered) {
6722                 *returned=0;
6723                 return WERR_INSUFFICIENT_BUFFER;
6724         }
6725
6726         return WERR_OK;
6727 }
6728
6729 /****************************************************************************
6730  Enumerates all printer drivers at level 2.
6731 ****************************************************************************/
6732
6733 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6734 {
6735         int i;
6736         int ndrivers;
6737         uint32 version;
6738         fstring *list = NULL;
6739
6740         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6741         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6742
6743         *returned=0;
6744
6745         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6746                 list=NULL;
6747                 ndrivers=get_ntdrivers(&list, architecture, version);
6748                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6749
6750                 if(ndrivers == -1)
6751                         return WERR_NOMEM;
6752
6753                 if(ndrivers != 0) {
6754                         if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6755                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6756                                 SAFE_FREE(driver_info_2);
6757                                 SAFE_FREE(list);
6758                                 return WERR_NOMEM;
6759                         }
6760                         else driver_info_2 = tdi2;
6761                 }
6762                 
6763                 for (i=0; i<ndrivers; i++) {
6764                         WERROR status;
6765
6766                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6767                         ZERO_STRUCT(driver);
6768                         status = get_a_printer_driver(&driver, 3, list[i], 
6769                                                       architecture, version);
6770                         if (!W_ERROR_IS_OK(status)) {
6771                                 SAFE_FREE(list);
6772                                 return status;
6773                         }
6774                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
6775                         free_a_printer_driver(driver, 3);
6776                 }       
6777
6778                 *returned+=ndrivers;
6779                 SAFE_FREE(list);
6780         }
6781         
6782         /* check the required size. */
6783         for (i=0; i<*returned; i++) {
6784                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6785                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6786         }
6787
6788         if (!alloc_buffer_size(buffer, *needed)) {
6789                 SAFE_FREE(driver_info_2);
6790                 return WERR_INSUFFICIENT_BUFFER;
6791         }
6792
6793         /* fill the buffer with the form structures */
6794         for (i=0; i<*returned; i++) {
6795                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6796                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6797         }
6798
6799         SAFE_FREE(driver_info_2);
6800
6801         if (*needed > offered) {
6802                 *returned=0;
6803                 return WERR_INSUFFICIENT_BUFFER;
6804         }
6805
6806         return WERR_OK;
6807 }
6808
6809 /****************************************************************************
6810  Enumerates all printer drivers at level 3.
6811 ****************************************************************************/
6812
6813 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6814 {
6815         int i;
6816         int ndrivers;
6817         uint32 version;
6818         fstring *list = NULL;
6819
6820         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6821         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6822
6823         *returned=0;
6824
6825         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6826                 list=NULL;
6827                 ndrivers=get_ntdrivers(&list, architecture, version);
6828                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6829
6830                 if(ndrivers == -1)
6831                         return WERR_NOMEM;
6832
6833                 if(ndrivers != 0) {
6834                         if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6835                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6836                                 SAFE_FREE(driver_info_3);
6837                                 SAFE_FREE(list);
6838                                 return WERR_NOMEM;
6839                         }
6840                         else driver_info_3 = tdi3;
6841                 }
6842
6843                 for (i=0; i<ndrivers; i++) {
6844                         WERROR status;
6845
6846                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6847                         ZERO_STRUCT(driver);
6848                         status = get_a_printer_driver(&driver, 3, list[i], 
6849                                                       architecture, version);
6850                         if (!W_ERROR_IS_OK(status)) {
6851                                 SAFE_FREE(list);
6852                                 return status;
6853                         }
6854                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
6855                         free_a_printer_driver(driver, 3);
6856                 }       
6857
6858                 *returned+=ndrivers;
6859                 SAFE_FREE(list);
6860         }
6861
6862         /* check the required size. */
6863         for (i=0; i<*returned; i++) {
6864                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6865                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6866         }
6867
6868         if (!alloc_buffer_size(buffer, *needed)) {
6869                 SAFE_FREE(driver_info_3);
6870                 return WERR_INSUFFICIENT_BUFFER;
6871         }
6872         
6873         /* fill the buffer with the driver structures */
6874         for (i=0; i<*returned; i++) {
6875                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6876                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6877         }
6878
6879         for (i=0; i<*returned; i++)
6880                 SAFE_FREE(driver_info_3[i].dependentfiles);
6881         
6882         SAFE_FREE(driver_info_3);
6883         
6884         if (*needed > offered) {
6885                 *returned=0;
6886                 return WERR_INSUFFICIENT_BUFFER;
6887         }
6888
6889         return WERR_OK;
6890 }
6891
6892 /****************************************************************************
6893  Enumerates all printer drivers.
6894 ****************************************************************************/
6895
6896 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6897 {
6898         uint32 level = q_u->level;
6899         NEW_BUFFER *buffer = NULL;
6900         uint32 offered = q_u->offered;
6901         uint32 *needed = &r_u->needed;
6902         uint32 *returned = &r_u->returned;
6903
6904         fstring *list = NULL;
6905         fstring servername;
6906         fstring architecture;
6907
6908         /* that's an [in out] buffer */
6909         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6910         buffer = r_u->buffer;
6911
6912         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6913         *needed=0;
6914         *returned=0;
6915
6916         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6917         unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6918
6919         if ( !is_myname_or_ipaddr( servername ) )
6920                 return WERR_UNKNOWN_PRINTER_DRIVER;
6921
6922         switch (level) {
6923         case 1:
6924                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6925         case 2:
6926                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6927         case 3:
6928                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6929         default:
6930                 *returned=0;
6931                 SAFE_FREE(list);
6932                 return WERR_UNKNOWN_LEVEL;
6933         }
6934 }
6935
6936 /****************************************************************************
6937 ****************************************************************************/
6938
6939 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6940 {
6941         form->flag=list->flag;
6942         init_unistr(&form->name, list->name);
6943         form->width=list->width;
6944         form->length=list->length;
6945         form->left=list->left;
6946         form->top=list->top;
6947         form->right=list->right;
6948         form->bottom=list->bottom;      
6949 }
6950         
6951 /****************************************************************************
6952 ****************************************************************************/
6953
6954 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6955 {
6956         uint32 level = q_u->level;
6957         NEW_BUFFER *buffer = NULL;
6958         uint32 offered = q_u->offered;
6959         uint32 *needed = &r_u->needed;
6960         uint32 *numofforms = &r_u->numofforms;
6961         uint32 numbuiltinforms;
6962
6963         nt_forms_struct *list=NULL;
6964         nt_forms_struct *builtinlist=NULL;
6965         FORM_1 *forms_1;
6966         int buffer_size=0;
6967         int i;
6968
6969         /* that's an [in out] buffer */
6970         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6971         buffer = r_u->buffer;
6972
6973         DEBUG(4,("_spoolss_enumforms\n"));
6974         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6975         DEBUGADD(5,("Info level [%d]\n",          level));
6976
6977         numbuiltinforms = get_builtin_ntforms(&builtinlist);
6978         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
6979         *numofforms = get_ntforms(&list);
6980         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
6981         *numofforms += numbuiltinforms;
6982
6983         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6984
6985         switch (level) {
6986         case 1:
6987                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6988                         *numofforms=0;
6989                         return WERR_NOMEM;
6990                 }
6991
6992                 /* construct the list of form structures */
6993                 for (i=0; i<numbuiltinforms; i++) {
6994                         DEBUGADD(6,("Filling form number [%d]\n",i));
6995                         fill_form_1(&forms_1[i], &builtinlist[i]);
6996                 }
6997                 
6998                 SAFE_FREE(builtinlist);
6999
7000                 for (; i<*numofforms; i++) {
7001                         DEBUGADD(6,("Filling form number [%d]\n",i));
7002                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7003                 }
7004                 
7005                 SAFE_FREE(list);
7006
7007                 /* check the required size. */
7008                 for (i=0; i<numbuiltinforms; i++) {
7009                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7010                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7011                 }
7012                 for (; i<*numofforms; i++) {
7013                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7014                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7015                 }
7016
7017                 *needed=buffer_size;            
7018                 
7019                 if (!alloc_buffer_size(buffer, buffer_size)){
7020                         SAFE_FREE(forms_1);
7021                         return WERR_INSUFFICIENT_BUFFER;
7022                 }
7023
7024                 /* fill the buffer with the form structures */
7025                 for (i=0; i<numbuiltinforms; i++) {
7026                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7027                         smb_io_form_1("", buffer, &forms_1[i], 0);
7028                 }
7029                 for (; i<*numofforms; i++) {
7030                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7031                         smb_io_form_1("", buffer, &forms_1[i], 0);
7032                 }
7033
7034                 SAFE_FREE(forms_1);
7035
7036                 if (*needed > offered) {
7037                         *numofforms=0;
7038                         return WERR_INSUFFICIENT_BUFFER;
7039                 }
7040                 else
7041                         return WERR_OK;
7042                         
7043         default:
7044                 SAFE_FREE(list);
7045                 SAFE_FREE(builtinlist);
7046                 return WERR_UNKNOWN_LEVEL;
7047         }
7048
7049 }
7050
7051 /****************************************************************************
7052 ****************************************************************************/
7053
7054 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7055 {
7056         uint32 level = q_u->level;
7057         UNISTR2 *uni_formname = &q_u->formname;
7058         NEW_BUFFER *buffer = NULL;
7059         uint32 offered = q_u->offered;
7060         uint32 *needed = &r_u->needed;
7061
7062         nt_forms_struct *list=NULL;
7063         nt_forms_struct builtin_form;
7064         BOOL foundBuiltin;
7065         FORM_1 form_1;
7066         fstring form_name;
7067         int buffer_size=0;
7068         int numofforms=0, i=0;
7069
7070         /* that's an [in out] buffer */
7071         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7072         buffer = r_u->buffer;
7073
7074         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7075
7076         DEBUG(4,("_spoolss_getform\n"));
7077         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7078         DEBUGADD(5,("Info level [%d]\n",          level));
7079
7080         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7081         if (!foundBuiltin) {
7082                 numofforms = get_ntforms(&list);
7083                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7084
7085                 if (numofforms == 0)
7086                         return WERR_BADFID;
7087         }
7088
7089         switch (level) {
7090         case 1:
7091                 if (foundBuiltin) {
7092                         fill_form_1(&form_1, &builtin_form);
7093                 } else {
7094
7095                         /* Check if the requested name is in the list of form structures */
7096                         for (i=0; i<numofforms; i++) {
7097
7098                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7099
7100                                 if (strequal(form_name, list[i].name)) {
7101                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7102                                         fill_form_1(&form_1, &list[i]);
7103                                         break;
7104                                 }
7105                         }
7106                         
7107                         SAFE_FREE(list);
7108                         if (i == numofforms) {
7109                                 return WERR_BADFID;
7110                         }
7111                 }
7112                 /* check the required size. */
7113
7114                 *needed=spoolss_size_form_1(&form_1);
7115                 
7116                 if (!alloc_buffer_size(buffer, buffer_size)){
7117                         return WERR_INSUFFICIENT_BUFFER;
7118                 }
7119
7120                 if (*needed > offered) {
7121                         return WERR_INSUFFICIENT_BUFFER;
7122                 }
7123
7124                 /* fill the buffer with the form structures */
7125                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7126                 smb_io_form_1("", buffer, &form_1, 0);
7127
7128                 return WERR_OK;
7129                         
7130         default:
7131                 SAFE_FREE(list);
7132                 return WERR_UNKNOWN_LEVEL;
7133         }
7134 }
7135
7136 /****************************************************************************
7137 ****************************************************************************/
7138
7139 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7140 {
7141         init_unistr(&port->port_name, name);
7142 }
7143
7144 /****************************************************************************
7145 ****************************************************************************/
7146
7147 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7148 {
7149         init_unistr(&port->port_name, name);
7150         init_unistr(&port->monitor_name, "Local Monitor");
7151         init_unistr(&port->description, "Local Port");
7152         port->port_type=PORT_TYPE_WRITE;
7153         port->reserved=0x0;     
7154 }
7155
7156 /****************************************************************************
7157  enumports level 1.
7158 ****************************************************************************/
7159
7160 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7161 {
7162         PORT_INFO_1 *ports=NULL;
7163         int i=0;
7164
7165         if (*lp_enumports_cmd()) {
7166                 char *cmd = lp_enumports_cmd();
7167                 char **qlines;
7168                 pstring command;
7169                 int numlines;
7170                 int ret;
7171                 int fd;
7172
7173                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7174
7175                 DEBUG(10,("Running [%s]\n", command));
7176                 ret = smbrun(command, &fd);
7177                 DEBUG(10,("Returned [%d]\n", ret));
7178                 if (ret != 0) {
7179                         if (fd != -1)
7180                                 close(fd);
7181                         /* Is this the best error to return here? */
7182                         return WERR_ACCESS_DENIED;
7183                 }
7184
7185                 numlines = 0;
7186                 qlines = fd_lines_load(fd, &numlines);
7187                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7188                 close(fd);
7189
7190                 if(numlines) {
7191                         if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7192                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
7193                                           dos_errstr(WERR_NOMEM)));
7194                                 file_lines_free(qlines);
7195                                 return WERR_NOMEM;
7196                         }
7197
7198                         for (i=0; i<numlines; i++) {
7199                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7200                                 fill_port_1(&ports[i], qlines[i]);
7201                         }
7202
7203                         file_lines_free(qlines);
7204                 }
7205
7206                 *returned = numlines;
7207
7208         } else {
7209                 *returned = 1; /* Sole Samba port returned. */
7210
7211                 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7212                         return WERR_NOMEM;
7213         
7214                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7215
7216                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7217         }
7218
7219         /* check the required size. */
7220         for (i=0; i<*returned; i++) {
7221                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7222                 *needed += spoolss_size_port_info_1(&ports[i]);
7223         }
7224                 
7225         if (!alloc_buffer_size(buffer, *needed)) {
7226                 SAFE_FREE(ports);
7227                 return WERR_INSUFFICIENT_BUFFER;
7228         }
7229
7230         /* fill the buffer with the ports structures */
7231         for (i=0; i<*returned; i++) {
7232                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7233                 smb_io_port_1("", buffer, &ports[i], 0);
7234         }
7235
7236         SAFE_FREE(ports);
7237
7238         if (*needed > offered) {
7239                 *returned=0;
7240                 return WERR_INSUFFICIENT_BUFFER;
7241         }
7242
7243         return WERR_OK;
7244 }
7245
7246 /****************************************************************************
7247  enumports level 2.
7248 ****************************************************************************/
7249
7250 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7251 {
7252         PORT_INFO_2 *ports=NULL;
7253         int i=0;
7254
7255         if (*lp_enumports_cmd()) {
7256                 char *cmd = lp_enumports_cmd();
7257                 char *path;
7258                 char **qlines;
7259                 pstring tmp_file;
7260                 pstring command;
7261                 int numlines;
7262                 int ret;
7263                 int fd;
7264
7265                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7266                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7267                 else
7268                         path = lp_lockdir();
7269
7270                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7271                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7272
7273                 unlink(tmp_file);
7274                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7275                 ret = smbrun(command, &fd);
7276                 DEBUGADD(10,("returned [%d]\n", ret));
7277                 if (ret != 0) {
7278                         if (fd != -1)
7279                                 close(fd);
7280                         /* Is this the best error to return here? */
7281                         return WERR_ACCESS_DENIED;
7282                 }
7283
7284                 numlines = 0;
7285                 qlines = fd_lines_load(fd, &numlines);
7286                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7287                 close(fd);
7288
7289                 if(numlines) {
7290                         if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7291                                 file_lines_free(qlines);
7292                                 return WERR_NOMEM;
7293                         }
7294
7295                         for (i=0; i<numlines; i++) {
7296                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7297                                 fill_port_2(&(ports[i]), qlines[i]);
7298                         }
7299
7300                         file_lines_free(qlines);
7301                 }
7302
7303                 *returned = numlines;
7304
7305         } else {
7306
7307                 *returned = 1;
7308
7309                 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7310                         return WERR_NOMEM;
7311         
7312                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7313
7314                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7315         }
7316
7317         /* check the required size. */
7318         for (i=0; i<*returned; i++) {
7319                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7320                 *needed += spoolss_size_port_info_2(&ports[i]);
7321         }
7322                 
7323         if (!alloc_buffer_size(buffer, *needed)) {
7324                 SAFE_FREE(ports);
7325                 return WERR_INSUFFICIENT_BUFFER;
7326         }
7327
7328         /* fill the buffer with the ports structures */
7329         for (i=0; i<*returned; i++) {
7330                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7331                 smb_io_port_2("", buffer, &ports[i], 0);
7332         }
7333
7334         SAFE_FREE(ports);
7335
7336         if (*needed > offered) {
7337                 *returned=0;
7338                 return WERR_INSUFFICIENT_BUFFER;
7339         }
7340
7341         return WERR_OK;
7342 }
7343
7344 /****************************************************************************
7345  enumports.
7346 ****************************************************************************/
7347
7348 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7349 {
7350         uint32 level = q_u->level;
7351         NEW_BUFFER *buffer = NULL;
7352         uint32 offered = q_u->offered;
7353         uint32 *needed = &r_u->needed;
7354         uint32 *returned = &r_u->returned;
7355
7356         /* that's an [in out] buffer */
7357         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7358         buffer = r_u->buffer;
7359
7360         DEBUG(4,("_spoolss_enumports\n"));
7361         
7362         *returned=0;
7363         *needed=0;
7364         
7365         switch (level) {
7366         case 1:
7367                 return enumports_level_1(buffer, offered, needed, returned);
7368         case 2:
7369                 return enumports_level_2(buffer, offered, needed, returned);
7370         default:
7371                 return WERR_UNKNOWN_LEVEL;
7372         }
7373 }
7374
7375 /****************************************************************************
7376 ****************************************************************************/
7377
7378 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7379                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7380                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7381                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7382                                 POLICY_HND *handle)
7383 {
7384         NT_PRINTER_INFO_LEVEL *printer = NULL;
7385         fstring name;
7386         int     snum;
7387         WERROR err = WERR_OK;
7388
7389         if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7390                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7391                 return WERR_NOMEM;
7392         }
7393
7394         ZERO_STRUCTP(printer);
7395
7396         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7397         if (!convert_printer_info(info, printer, 2)) {
7398                 free_a_printer(&printer, 2);
7399                 return WERR_NOMEM;
7400         }
7401
7402         /* check to see if the printer already exists */
7403
7404         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7405                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
7406                         printer->info_2->sharename));
7407                 free_a_printer(&printer, 2);
7408                 return WERR_PRINTER_ALREADY_EXISTS;
7409         }
7410         
7411         /* FIXME!!!  smbd should check to see if the driver is installed before
7412            trying to add a printer like this  --jerry */
7413
7414         if (*lp_addprinter_cmd() ) {
7415                 if ( !add_printer_hook(printer) ) {
7416                         free_a_printer(&printer,2);
7417                         return WERR_ACCESS_DENIED;
7418         }
7419         }
7420
7421         /* use our primary netbios name since get_a_printer() will convert 
7422            it to what the client expects on a case by case basis */
7423
7424         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7425              printer->info_2->sharename);
7426
7427         
7428         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7429                 free_a_printer(&printer,2);
7430                 return WERR_ACCESS_DENIED;
7431         }
7432
7433         /* you must be a printer admin to add a new printer */
7434         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7435                 free_a_printer(&printer,2);
7436                 return WERR_ACCESS_DENIED;              
7437         }
7438         
7439         /*
7440          * Do sanity check on the requested changes for Samba.
7441          */
7442
7443         if (!check_printer_ok(printer->info_2, snum)) {
7444                 free_a_printer(&printer,2);
7445                 return WERR_INVALID_PARAM;
7446         }
7447
7448         /*
7449          * When a printer is created, the drivername bound to the printer is used
7450          * to lookup previously saved driver initialization info, which is then 
7451          * bound to the new printer, simulating what happens in the Windows arch.
7452          */
7453
7454         if (!devmode)
7455         {
7456                 set_driver_init(printer, 2);
7457         }
7458         else 
7459         {
7460                 /* A valid devmode was included, convert and link it
7461                 */
7462                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7463
7464                 if (!convert_devicemode(printer->info_2->printername, devmode,
7465                                 &printer->info_2->devmode))
7466                         return  WERR_NOMEM;
7467         }
7468
7469         /* write the ASCII on disk */
7470         err = mod_a_printer(printer, 2);
7471         if (!W_ERROR_IS_OK(err)) {
7472                 free_a_printer(&printer,2);
7473                 return err;
7474         }
7475
7476         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7477                 /* Handle open failed - remove addition. */
7478                 del_a_printer(printer->info_2->sharename);
7479                 free_a_printer(&printer,2);
7480                 return WERR_ACCESS_DENIED;
7481         }
7482
7483         update_c_setprinter(False);
7484         free_a_printer(&printer,2);
7485
7486         return WERR_OK;
7487 }
7488
7489 /****************************************************************************
7490 ****************************************************************************/
7491
7492 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7493 {
7494         UNISTR2 *uni_srv_name = &q_u->server_name;
7495         uint32 level = q_u->level;
7496         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7497         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7498         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7499         uint32 user_switch = q_u->user_switch;
7500         SPOOL_USER_CTR *user = &q_u->user_ctr;
7501         POLICY_HND *handle = &r_u->handle;
7502
7503         switch (level) {
7504                 case 1:
7505                         /* we don't handle yet */
7506                         /* but I know what to do ... */
7507                         return WERR_UNKNOWN_LEVEL;
7508                 case 2:
7509                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7510                                                             devmode, sdb,
7511                                                             user_switch, user, handle);
7512                 default:
7513                         return WERR_UNKNOWN_LEVEL;
7514         }
7515 }
7516
7517 /****************************************************************************
7518 ****************************************************************************/
7519
7520 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7521 {
7522         uint32 level = q_u->level;
7523         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7524         WERROR err = WERR_OK;
7525         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7526         struct current_user user;
7527         fstring driver_name;
7528         uint32 version;
7529
7530         ZERO_STRUCT(driver);
7531
7532         get_current_user(&user, p);
7533         
7534         if (!convert_printer_driver_info(info, &driver, level)) {
7535                 err = WERR_NOMEM;
7536                 goto done;
7537         }
7538
7539         DEBUG(5,("Cleaning driver's information\n"));
7540         err = clean_up_driver_struct(driver, level, &user);
7541         if (!W_ERROR_IS_OK(err))
7542                 goto done;
7543
7544         DEBUG(5,("Moving driver to final destination\n"));
7545         if(!move_driver_to_download_area(driver, level, &user, &err)) {
7546                 if (W_ERROR_IS_OK(err))
7547                         err = WERR_ACCESS_DENIED;
7548                 goto done;
7549         }
7550
7551         if (add_a_printer_driver(driver, level)!=0) {
7552                 err = WERR_ACCESS_DENIED;
7553                 goto done;
7554         }
7555
7556         /* BEGIN_ADMIN_LOG */
7557         switch(level) {
7558             case 3:
7559                 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7560                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7561                         driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7562                 break;
7563             case 6:   
7564                 fstrcpy(driver_name, driver.info_6->name ?  driver.info_6->name : "");
7565                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7566                         driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7567                 break;
7568         }
7569         /* END_ADMIN_LOG */
7570
7571         /* 
7572          * I think this is where he DrvUpgradePrinter() hook would be
7573          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7574          * server.  Right now, we just need to send ourselves a message
7575          * to update each printer bound to this driver.   --jerry       
7576          */
7577          
7578         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7579                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7580                         driver_name));
7581         }
7582
7583         /*
7584          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7585          * decide if the driver init data should be deleted. The rules are:
7586          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7587          *  2) delete init data only if there is no 2k/Xp driver
7588          *  3) always delete init data
7589          * The generalized rule is always use init data from the highest order driver.
7590          * It is necessary to follow the driver install by an initialization step to
7591          * finish off this process.
7592         */
7593         if (level == 3)
7594                 version = driver.info_3->cversion;
7595         else if (level == 6)
7596                 version = driver.info_6->version;
7597         else
7598                 version = -1;
7599         switch (version) {
7600                 /*
7601                  * 9x printer driver - never delete init data
7602                 */
7603                 case 0: 
7604                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7605                                         driver_name));
7606                         break;
7607                 
7608                 /*
7609                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7610                  * there is no 2k/Xp driver init data for this driver name.
7611                 */
7612                 case 2:
7613                 {
7614                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7615
7616                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7617                                 /*
7618                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7619                                 */
7620                                 if (!del_driver_init(driver_name))
7621                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7622                         } else {
7623                                 /*
7624                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7625                                 */
7626                                 free_a_printer_driver(driver1,3);
7627                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", 
7628                                                 driver_name));
7629                         }
7630                 }
7631                 break;
7632
7633                 /*
7634                  * 2k or Xp printer driver - always delete init data
7635                 */
7636                 case 3: 
7637                         if (!del_driver_init(driver_name))
7638                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7639                         break;
7640
7641                 default:
7642                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7643                         break;
7644         }
7645
7646         
7647 done:
7648         free_a_printer_driver(driver, level);
7649         return err;
7650 }
7651
7652 /********************************************************************
7653  * spoolss_addprinterdriverex
7654  ********************************************************************/
7655
7656 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7657 {
7658         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7659         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7660         
7661         /* 
7662          * we only support the semantics of AddPrinterDriver()
7663          * i.e. only copy files that are newer than existing ones
7664          */
7665         
7666         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7667                 return WERR_ACCESS_DENIED;
7668         
7669         ZERO_STRUCT(q_u_local);
7670         ZERO_STRUCT(r_u_local);
7671
7672         /* just pass the information off to _spoolss_addprinterdriver() */
7673         q_u_local.server_name_ptr = q_u->server_name_ptr;
7674         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7675         q_u_local.level = q_u->level;
7676         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7677         
7678         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7679 }
7680
7681 /****************************************************************************
7682 ****************************************************************************/
7683
7684 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7685 {
7686         init_unistr(&info->name, name);
7687 }
7688
7689 /****************************************************************************
7690 ****************************************************************************/
7691
7692 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7693 {
7694         pstring path;
7695         pstring long_archi;
7696         fstring servername;
7697         char *pservername; 
7698         const char *short_archi;
7699         DRIVER_DIRECTORY_1 *info=NULL;
7700
7701         unistr2_to_ascii(servername, name, sizeof(servername)-1);
7702         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7703
7704         /* check for beginning double '\'s and that the server
7705            long enough */
7706
7707         pservername = servername;
7708         if ( *pservername == '\\' && strlen(servername)>2 ) {
7709                 pservername += 2;
7710         } 
7711         
7712         if ( !is_myname_or_ipaddr( pservername ) )
7713                 return WERR_INVALID_PARAM;
7714
7715         if (!(short_archi = get_short_archi(long_archi)))
7716                 return WERR_INVALID_ENVIRONMENT;
7717
7718         if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7719                 return WERR_NOMEM;
7720
7721         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7722
7723         DEBUG(4,("printer driver directory: [%s]\n", path));
7724
7725         fill_driverdir_1(info, path);
7726         
7727         *needed += spoolss_size_driverdir_info_1(info);
7728
7729         if (!alloc_buffer_size(buffer, *needed)) {
7730                 SAFE_FREE(info);
7731                 return WERR_INSUFFICIENT_BUFFER;
7732         }
7733
7734         smb_io_driverdir_1("", buffer, info, 0);
7735
7736         SAFE_FREE(info);
7737         
7738         if (*needed > offered)
7739                 return WERR_INSUFFICIENT_BUFFER;
7740
7741         return WERR_OK;
7742 }
7743
7744 /****************************************************************************
7745 ****************************************************************************/
7746
7747 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7748 {
7749         UNISTR2 *name = &q_u->name;
7750         UNISTR2 *uni_environment = &q_u->environment;
7751         uint32 level = q_u->level;
7752         NEW_BUFFER *buffer = NULL;
7753         uint32 offered = q_u->offered;
7754         uint32 *needed = &r_u->needed;
7755
7756         /* that's an [in out] buffer */
7757         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7758         buffer = r_u->buffer;
7759
7760         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7761
7762         *needed=0;
7763
7764         switch(level) {
7765         case 1:
7766                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7767         default:
7768                 return WERR_UNKNOWN_LEVEL;
7769         }
7770 }
7771         
7772 /****************************************************************************
7773 ****************************************************************************/
7774
7775 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7776 {
7777         POLICY_HND *handle = &q_u->handle;
7778         uint32 idx               = q_u->index;
7779         uint32 in_value_len      = q_u->valuesize;
7780         uint32 in_data_len       = q_u->datasize;
7781         uint32 *out_max_value_len = &r_u->valuesize;
7782         uint16 **out_value       = &r_u->value;
7783         uint32 *out_value_len    = &r_u->realvaluesize;
7784         uint32 *out_type         = &r_u->type;
7785         uint32 *out_max_data_len = &r_u->datasize;
7786         uint8  **data_out        = &r_u->data;
7787         uint32 *out_data_len     = &r_u->realdatasize;
7788
7789         NT_PRINTER_INFO_LEVEL *printer = NULL;
7790         
7791         uint32          biggest_valuesize;
7792         uint32          biggest_datasize;
7793         uint32          data_len;
7794         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7795         int             snum;
7796         WERROR          result;
7797         REGISTRY_VALUE  *val = NULL;
7798         NT_PRINTER_DATA *p_data;
7799         int             i, key_index, num_values;
7800         int             name_length;
7801         
7802         ZERO_STRUCT( printer );
7803         
7804         *out_type = 0;
7805
7806         *out_max_data_len = 0;
7807         *data_out         = NULL;
7808         *out_data_len     = 0;
7809
7810         DEBUG(5,("spoolss_enumprinterdata\n"));
7811
7812         if (!Printer) {
7813                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7814                 return WERR_BADFID;
7815         }
7816
7817         if (!get_printer_snum(p,handle, &snum))
7818                 return WERR_BADFID;
7819         
7820         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7821         if (!W_ERROR_IS_OK(result))
7822                 return result;
7823                 
7824         p_data = &printer->info_2->data;        
7825         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7826
7827         result = WERR_OK;
7828
7829         /*
7830          * The NT machine wants to know the biggest size of value and data
7831          *
7832          * cf: MSDN EnumPrinterData remark section
7833          */
7834          
7835         if ( !in_value_len && !in_data_len && (key_index != -1) ) 
7836         {
7837                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7838
7839                 biggest_valuesize = 0;
7840                 biggest_datasize  = 0;
7841                                 
7842                 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7843                 
7844                 for ( i=0; i<num_values; i++ )
7845                 {
7846                         val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7847                         
7848                         name_length = strlen(val->valuename);
7849                         if ( strlen(val->valuename) > biggest_valuesize ) 
7850                                 biggest_valuesize = name_length;
7851                                 
7852                         if ( val->size > biggest_datasize )
7853                                 biggest_datasize = val->size;
7854                                 
7855                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, 
7856                                 biggest_datasize));
7857                 }
7858
7859                 /* the value is an UNICODE string but real_value_size is the length 
7860                    in bytes including the trailing 0 */
7861                    
7862                 *out_value_len = 2 * (1+biggest_valuesize);
7863                 *out_data_len  = biggest_datasize;
7864
7865                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7866
7867                 goto done;
7868         }
7869         
7870         /*
7871          * the value len is wrong in NT sp3
7872          * that's the number of bytes not the number of unicode chars
7873          */
7874         
7875         if ( key_index != -1 )
7876                 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7877
7878         if ( !val ) 
7879         {
7880
7881                 /* out_value should default to "" or else NT4 has
7882                    problems unmarshalling the response */
7883
7884                 *out_max_value_len=(in_value_len/sizeof(uint16));
7885                 
7886                 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7887                 {
7888                         result = WERR_NOMEM;
7889                         goto done;
7890                 }
7891
7892                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7893
7894                 /* the data is counted in bytes */
7895                 
7896                 *out_max_data_len = in_data_len;
7897                 *out_data_len     = in_data_len;
7898                 
7899                 /* only allocate when given a non-zero data_len */
7900                 
7901                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7902                 {
7903                         result = WERR_NOMEM;
7904                         goto done;
7905                 }
7906
7907                 result = WERR_NO_MORE_ITEMS;
7908         }
7909         else 
7910         {
7911                 /*
7912                  * the value is:
7913                  * - counted in bytes in the request
7914                  * - counted in UNICODE chars in the max reply
7915                  * - counted in bytes in the real size
7916                  *
7917                  * take a pause *before* coding not *during* coding
7918                  */
7919         
7920                 /* name */
7921                 *out_max_value_len=(in_value_len/sizeof(uint16));
7922                 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
7923                 {
7924                         result = WERR_NOMEM;
7925                         goto done;
7926                 }
7927         
7928                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7929
7930                 /* type */
7931                 
7932                 *out_type = regval_type( val );
7933
7934                 /* data - counted in bytes */
7935
7936                 *out_max_data_len = in_data_len;
7937                 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
7938                 {
7939                         result = WERR_NOMEM;
7940                         goto done;
7941                 }
7942                 data_len = (size_t)regval_size(val);
7943                 memcpy( *data_out, regval_data_p(val), data_len );
7944                 *out_data_len = data_len;
7945         }
7946
7947 done:
7948         free_a_printer(&printer, 2);
7949         return result;
7950 }
7951
7952 /****************************************************************************
7953 ****************************************************************************/
7954
7955 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7956 {
7957         POLICY_HND              *handle = &q_u->handle;
7958         UNISTR2                 *value = &q_u->value;
7959         uint32                  type = q_u->type;
7960         uint8                   *data = q_u->data;
7961         uint32                  real_len = q_u->real_len;
7962
7963         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7964         int                     snum=0;
7965         WERROR                  status = WERR_OK;
7966         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
7967         fstring                 valuename;
7968         
7969         DEBUG(5,("spoolss_setprinterdata\n"));
7970
7971         if (!Printer) {
7972                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7973                 return WERR_BADFID;
7974         }
7975
7976         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7977                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7978                 return WERR_INVALID_PARAM;
7979         }
7980
7981         if (!get_printer_snum(p,handle, &snum))
7982                 return WERR_BADFID;
7983
7984         /* 
7985          * Access check : NT returns "access denied" if you make a 
7986          * SetPrinterData call without the necessary privildge.
7987          * we were originally returning OK if nothing changed
7988          * which made Win2k issue **a lot** of SetPrinterData
7989          * when connecting to a printer  --jerry
7990          */
7991
7992         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
7993         {
7994                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7995                 status = WERR_ACCESS_DENIED;
7996                 goto done;
7997         }
7998
7999         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8000         if (!W_ERROR_IS_OK(status))
8001                 return status;
8002
8003         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8004         
8005         /*
8006          * When client side code sets a magic printer data key, detect it and save
8007          * the current printer data and the magic key's data (its the DEVMODE) for
8008          * future printer/driver initializations.
8009          */
8010         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
8011         {
8012                 /* Set devmode and printer initialization info */
8013                 status = save_driver_init( printer, 2, data, real_len );
8014         
8015                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8016         }
8017         else 
8018         {
8019         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
8020                                         type, data, real_len );
8021                 if ( W_ERROR_IS_OK(status) )
8022                         status = mod_a_printer(printer, 2);
8023         }
8024
8025 done:
8026         free_a_printer(&printer, 2);
8027
8028         return status;
8029 }
8030
8031 /****************************************************************************
8032 ****************************************************************************/
8033
8034 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8035 {
8036         POLICY_HND      *handle = &q_u->handle;
8037         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8038         int             snum;
8039         
8040         DEBUG(5,("_spoolss_resetprinter\n"));
8041
8042         /*
8043          * All we do is to check to see if the handle and queue is valid.
8044          * This call really doesn't mean anything to us because we only
8045          * support RAW printing.   --jerry
8046          */
8047          
8048         if (!Printer) {
8049                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8050                 return WERR_BADFID;
8051         }
8052
8053         if (!get_printer_snum(p,handle, &snum))
8054                 return WERR_BADFID;
8055
8056
8057         /* blindly return success */    
8058         return WERR_OK;
8059 }
8060
8061
8062 /****************************************************************************
8063 ****************************************************************************/
8064
8065 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8066 {
8067         POLICY_HND      *handle = &q_u->handle;
8068         UNISTR2         *value = &q_u->valuename;
8069
8070         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8071         int             snum=0;
8072         WERROR          status = WERR_OK;
8073         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8074         pstring         valuename;
8075         
8076         DEBUG(5,("spoolss_deleteprinterdata\n"));
8077         
8078         if (!Printer) {
8079                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8080                 return WERR_BADFID;
8081         }
8082
8083         if (!get_printer_snum(p, handle, &snum))
8084                 return WERR_BADFID;
8085
8086         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8087                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8088                 return WERR_ACCESS_DENIED;
8089         }
8090
8091         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8092         if (!W_ERROR_IS_OK(status))
8093                 return status;
8094
8095         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8096
8097         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8098         
8099         if ( W_ERROR_IS_OK(status) )
8100                 mod_a_printer( printer, 2 );
8101
8102         free_a_printer(&printer, 2);
8103
8104         return status;
8105 }
8106
8107 /****************************************************************************
8108 ****************************************************************************/
8109
8110 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8111 {
8112         POLICY_HND *handle = &q_u->handle;
8113         FORM *form = &q_u->form;
8114         nt_forms_struct tmpForm;
8115         int snum;
8116         WERROR status = WERR_OK;
8117         NT_PRINTER_INFO_LEVEL *printer = NULL;
8118
8119         int count=0;
8120         nt_forms_struct *list=NULL;
8121         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8122
8123         DEBUG(5,("spoolss_addform\n"));
8124
8125         if (!Printer) {
8126                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8127                 return WERR_BADFID;
8128         }
8129         
8130         
8131         /* forms can be added on printer of on the print server handle */
8132         
8133         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8134         {
8135                 if (!get_printer_snum(p,handle, &snum))
8136                         return WERR_BADFID;
8137          
8138                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139                 if (!W_ERROR_IS_OK(status))
8140                         goto done;
8141         }
8142
8143         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8144                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8145                 status = WERR_ACCESS_DENIED;
8146                 goto done;
8147         }
8148         
8149         /* can't add if builtin */
8150         
8151         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8152                 status = WERR_ALREADY_EXISTS;
8153                 goto done;
8154         }
8155
8156         count = get_ntforms(&list);
8157         
8158         if(!add_a_form(&list, form, &count)) {
8159                 status =  WERR_NOMEM;
8160                 goto done;
8161         }
8162         
8163         write_ntforms(&list, count);
8164         
8165         /*
8166          * ChangeID must always be set if this is a printer
8167          */
8168          
8169         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8170                 status = mod_a_printer(printer, 2);
8171         
8172 done:
8173         if ( printer )
8174                 free_a_printer(&printer, 2);
8175         SAFE_FREE(list);
8176
8177         return status;
8178 }
8179
8180 /****************************************************************************
8181 ****************************************************************************/
8182
8183 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8184 {
8185         POLICY_HND *handle = &q_u->handle;
8186         UNISTR2 *form_name = &q_u->name;
8187         nt_forms_struct tmpForm;
8188         int count=0;
8189         nt_forms_struct *list=NULL;
8190         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8191         int snum;
8192         WERROR status = WERR_OK;
8193         NT_PRINTER_INFO_LEVEL *printer = NULL;
8194
8195         DEBUG(5,("spoolss_deleteform\n"));
8196
8197         if (!Printer) {
8198                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8199                 return WERR_BADFID;
8200         }
8201
8202         /* forms can be deleted on printer of on the print server handle */
8203         
8204         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8205         {
8206                 if (!get_printer_snum(p,handle, &snum))
8207                         return WERR_BADFID;
8208          
8209                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8210                 if (!W_ERROR_IS_OK(status))
8211                         goto done;
8212         }
8213
8214         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8215                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8216                 status = WERR_ACCESS_DENIED;
8217                 goto done;
8218         }
8219
8220         /* can't delete if builtin */
8221         
8222         if (get_a_builtin_ntform(form_name,&tmpForm)) {
8223                 status = WERR_INVALID_PARAM;
8224                 goto done;
8225         }
8226
8227         count = get_ntforms(&list);
8228         
8229         if ( !delete_a_form(&list, form_name, &count, &status ))
8230                 goto done;
8231
8232         /*
8233          * ChangeID must always be set if this is a printer
8234          */
8235          
8236         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8237                 status = mod_a_printer(printer, 2);
8238         
8239 done:
8240         if ( printer )
8241                 free_a_printer(&printer, 2);
8242         SAFE_FREE(list);
8243
8244         return status;
8245 }
8246
8247 /****************************************************************************
8248 ****************************************************************************/
8249
8250 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8251 {
8252         POLICY_HND *handle = &q_u->handle;
8253         FORM *form = &q_u->form;
8254         nt_forms_struct tmpForm;
8255         int snum;
8256         WERROR status = WERR_OK;
8257         NT_PRINTER_INFO_LEVEL *printer = NULL;
8258
8259         int count=0;
8260         nt_forms_struct *list=NULL;
8261         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8262
8263         DEBUG(5,("spoolss_setform\n"));
8264
8265         if (!Printer) {
8266                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8267                 return WERR_BADFID;
8268         }
8269
8270         /* forms can be modified on printer of on the print server handle */
8271         
8272         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8273         {
8274                 if (!get_printer_snum(p,handle, &snum))
8275                         return WERR_BADFID;
8276          
8277                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8278                 if (!W_ERROR_IS_OK(status))
8279                         goto done;
8280         }
8281
8282         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8283                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8284                 status = WERR_ACCESS_DENIED;
8285                 goto done;
8286         }
8287
8288         /* can't set if builtin */
8289         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8290                 status = WERR_INVALID_PARAM;
8291                 goto done;
8292         }
8293
8294         count = get_ntforms(&list);
8295         update_a_form(&list, form, count);
8296         write_ntforms(&list, count);
8297
8298         /*
8299          * ChangeID must always be set if this is a printer
8300          */
8301          
8302         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8303                 status = mod_a_printer(printer, 2);
8304         
8305         
8306 done:
8307         if ( printer )
8308                 free_a_printer(&printer, 2);
8309         SAFE_FREE(list);
8310
8311         return status;
8312 }
8313
8314 /****************************************************************************
8315  enumprintprocessors level 1.
8316 ****************************************************************************/
8317
8318 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8319 {
8320         PRINTPROCESSOR_1 *info_1=NULL;
8321         
8322         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8323                 return WERR_NOMEM;
8324
8325         (*returned) = 0x1;
8326         
8327         init_unistr(&info_1->name, "winprint");
8328
8329         *needed += spoolss_size_printprocessor_info_1(info_1);
8330
8331         if (!alloc_buffer_size(buffer, *needed))
8332                 return WERR_INSUFFICIENT_BUFFER;
8333
8334         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8335
8336         SAFE_FREE(info_1);
8337
8338         if (*needed > offered) {
8339                 *returned=0;
8340                 return WERR_INSUFFICIENT_BUFFER;
8341         }
8342
8343         return WERR_OK;
8344 }
8345
8346 /****************************************************************************
8347 ****************************************************************************/
8348
8349 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8350 {
8351         uint32 level = q_u->level;
8352         NEW_BUFFER *buffer = NULL;
8353         uint32 offered = q_u->offered;
8354         uint32 *needed = &r_u->needed;
8355         uint32 *returned = &r_u->returned;
8356
8357         /* that's an [in out] buffer */
8358         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8359         buffer = r_u->buffer;
8360
8361         DEBUG(5,("spoolss_enumprintprocessors\n"));
8362
8363         /*
8364          * Enumerate the print processors ...
8365          *
8366          * Just reply with "winprint", to keep NT happy
8367          * and I can use my nice printer checker.
8368          */
8369         
8370         *returned=0;
8371         *needed=0;
8372         
8373         switch (level) {
8374         case 1:
8375                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8376         default:
8377                 return WERR_UNKNOWN_LEVEL;
8378         }
8379 }
8380
8381 /****************************************************************************
8382  enumprintprocdatatypes level 1.
8383 ****************************************************************************/
8384
8385 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8386 {
8387         PRINTPROCDATATYPE_1 *info_1=NULL;
8388         
8389         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8390                 return WERR_NOMEM;
8391
8392         (*returned) = 0x1;
8393         
8394         init_unistr(&info_1->name, "RAW");
8395
8396         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8397
8398         if (!alloc_buffer_size(buffer, *needed))
8399                 return WERR_INSUFFICIENT_BUFFER;
8400
8401         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8402
8403         SAFE_FREE(info_1);
8404
8405         if (*needed > offered) {
8406                 *returned=0;
8407                 return WERR_INSUFFICIENT_BUFFER;
8408         }
8409
8410         return WERR_OK;
8411 }
8412
8413 /****************************************************************************
8414 ****************************************************************************/
8415
8416 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8417 {
8418         uint32 level = q_u->level;
8419         NEW_BUFFER *buffer = NULL;
8420         uint32 offered = q_u->offered;
8421         uint32 *needed = &r_u->needed;
8422         uint32 *returned = &r_u->returned;
8423
8424         /* that's an [in out] buffer */
8425         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8426         buffer = r_u->buffer;
8427
8428         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8429         
8430         *returned=0;
8431         *needed=0;
8432         
8433         switch (level) {
8434         case 1:
8435                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8436         default:
8437                 return WERR_UNKNOWN_LEVEL;
8438         }
8439 }
8440
8441 /****************************************************************************
8442  enumprintmonitors level 1.
8443 ****************************************************************************/
8444
8445 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8446 {
8447         PRINTMONITOR_1 *info_1=NULL;
8448         
8449         if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8450                 return WERR_NOMEM;
8451
8452         (*returned) = 0x1;
8453         
8454         init_unistr(&info_1->name, "Local Port");
8455
8456         *needed += spoolss_size_printmonitor_info_1(info_1);
8457
8458         if (!alloc_buffer_size(buffer, *needed))
8459                 return WERR_INSUFFICIENT_BUFFER;
8460
8461         smb_io_printmonitor_info_1("", buffer, info_1, 0);
8462
8463         SAFE_FREE(info_1);
8464
8465         if (*needed > offered) {
8466                 *returned=0;
8467                 return WERR_INSUFFICIENT_BUFFER;
8468         }
8469
8470         return WERR_OK;
8471 }
8472
8473 /****************************************************************************
8474  enumprintmonitors level 2.
8475 ****************************************************************************/
8476
8477 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8478 {
8479         PRINTMONITOR_2 *info_2=NULL;
8480         
8481         if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8482                 return WERR_NOMEM;
8483
8484         (*returned) = 0x1;
8485         
8486         init_unistr(&info_2->name, "Local Port");
8487         init_unistr(&info_2->environment, "Windows NT X86");
8488         init_unistr(&info_2->dll_name, "localmon.dll");
8489
8490         *needed += spoolss_size_printmonitor_info_2(info_2);
8491
8492         if (!alloc_buffer_size(buffer, *needed))
8493                 return WERR_INSUFFICIENT_BUFFER;
8494
8495         smb_io_printmonitor_info_2("", buffer, info_2, 0);
8496
8497         SAFE_FREE(info_2);
8498
8499         if (*needed > offered) {
8500                 *returned=0;
8501                 return WERR_INSUFFICIENT_BUFFER;
8502         }
8503
8504         return WERR_OK;
8505 }
8506
8507 /****************************************************************************
8508 ****************************************************************************/
8509
8510 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8511 {
8512         uint32 level = q_u->level;
8513         NEW_BUFFER *buffer = NULL;
8514         uint32 offered = q_u->offered;
8515         uint32 *needed = &r_u->needed;
8516         uint32 *returned = &r_u->returned;
8517
8518         /* that's an [in out] buffer */
8519         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8520         buffer = r_u->buffer;
8521
8522         DEBUG(5,("spoolss_enumprintmonitors\n"));
8523
8524         /*
8525          * Enumerate the print monitors ...
8526          *
8527          * Just reply with "Local Port", to keep NT happy
8528          * and I can use my nice printer checker.
8529          */
8530         
8531         *returned=0;
8532         *needed=0;
8533         
8534         switch (level) {
8535         case 1:
8536                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8537         case 2:
8538                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8539         default:
8540                 return WERR_UNKNOWN_LEVEL;
8541         }
8542 }
8543
8544 /****************************************************************************
8545 ****************************************************************************/
8546
8547 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8548                              NT_PRINTER_INFO_LEVEL *ntprinter,
8549                              uint32 jobid, NEW_BUFFER *buffer, uint32 offered, 
8550                              uint32 *needed)
8551 {
8552         int i=0;
8553         BOOL found=False;
8554         JOB_INFO_1 *info_1=NULL;
8555
8556         info_1=SMB_MALLOC_P(JOB_INFO_1);
8557
8558         if (info_1 == NULL) {
8559                 return WERR_NOMEM;
8560         }
8561                 
8562         for (i=0; i<count && found==False; i++) { 
8563                 if ((*queue)[i].job==(int)jobid)
8564                         found=True;
8565         }
8566         
8567         if (found==False) {
8568                 SAFE_FREE(info_1);
8569                 /* NT treats not found as bad param... yet another bad choice */
8570                 return WERR_INVALID_PARAM;
8571         }
8572         
8573         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8574         
8575         *needed += spoolss_size_job_info_1(info_1);
8576
8577         if (!alloc_buffer_size(buffer, *needed)) {
8578                 SAFE_FREE(info_1);
8579                 return WERR_INSUFFICIENT_BUFFER;
8580         }
8581
8582         smb_io_job_info_1("", buffer, info_1, 0);
8583
8584         SAFE_FREE(info_1);
8585
8586         if (*needed > offered)
8587                 return WERR_INSUFFICIENT_BUFFER;
8588
8589         return WERR_OK;
8590 }
8591
8592 /****************************************************************************
8593 ****************************************************************************/
8594
8595 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, 
8596                              NT_PRINTER_INFO_LEVEL *ntprinter,
8597                              uint32 jobid, NEW_BUFFER *buffer, uint32 offered, 
8598                              uint32 *needed)
8599 {
8600         int             i = 0;
8601         BOOL            found = False;
8602         JOB_INFO_2      *info_2;
8603         WERROR          ret;
8604         DEVICEMODE      *devmode = NULL;
8605         NT_DEVICEMODE   *nt_devmode = NULL;
8606
8607         info_2=SMB_MALLOC_P(JOB_INFO_2);
8608
8609         ZERO_STRUCTP(info_2);
8610
8611         if (info_2 == NULL) {
8612                 ret = WERR_NOMEM;
8613                 goto done;
8614         }
8615
8616         for ( i=0; i<count && found==False; i++ ) 
8617         {
8618                 if ((*queue)[i].job == (int)jobid)
8619                         found = True;
8620         }
8621         
8622         if ( !found ) 
8623         {
8624                 /* NT treats not found as bad param... yet another bad
8625                    choice */
8626                 ret = WERR_INVALID_PARAM;
8627                 goto done;
8628         }
8629         
8630         /* 
8631          * if the print job does not have a DEVMODE associated with it, 
8632          * just use the one for the printer. A NULL devicemode is not
8633          *  a failure condition
8634          */
8635          
8636         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8637                 devmode = construct_dev_mode(snum);
8638         else {
8639                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8640                         ZERO_STRUCTP( devmode );
8641                         convert_nt_devicemode( devmode, nt_devmode );
8642                 }
8643         }
8644         
8645         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8646         
8647         *needed += spoolss_size_job_info_2(info_2);
8648
8649         if (!alloc_buffer_size(buffer, *needed)) {
8650                 ret = WERR_INSUFFICIENT_BUFFER;
8651                 goto done;
8652         }
8653
8654         smb_io_job_info_2("", buffer, info_2, 0);
8655
8656         if (*needed > offered) {
8657                 ret = WERR_INSUFFICIENT_BUFFER;
8658                 goto done;
8659         }
8660
8661         ret = WERR_OK;
8662         
8663  done:
8664         /* Cleanup allocated memory */
8665
8666         free_job_info_2(info_2);        /* Also frees devmode */
8667         SAFE_FREE(info_2);
8668
8669         return ret;
8670 }
8671
8672 /****************************************************************************
8673 ****************************************************************************/
8674
8675 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8676 {
8677         POLICY_HND *handle = &q_u->handle;
8678         uint32 jobid = q_u->jobid;
8679         uint32 level = q_u->level;
8680         NEW_BUFFER *buffer = NULL;
8681         uint32 offered = q_u->offered;
8682         uint32 *needed = &r_u->needed;
8683         WERROR          wstatus = WERR_OK;
8684         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8685         int snum;
8686         int count;
8687         print_queue_struct      *queue = NULL;
8688         print_status_struct prt_status;
8689
8690         /* that's an [in out] buffer */
8691         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8692         buffer = r_u->buffer;
8693
8694         DEBUG(5,("spoolss_getjob\n"));
8695         
8696         *needed = 0;
8697         
8698         if (!get_printer_snum(p, handle, &snum))
8699                 return WERR_BADFID;
8700         
8701         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8702         if ( !W_ERROR_IS_OK(wstatus) )
8703                 return wstatus;
8704                 
8705         count = print_queue_status(snum, &queue, &prt_status);
8706         
8707         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8708                      count, prt_status.status, prt_status.message));
8709                 
8710         switch ( level ) {
8711         case 1:
8712                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid, 
8713                                 buffer, offered, needed);
8714                         break;
8715         case 2:
8716                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid, 
8717                                 buffer, offered, needed);
8718                         break;
8719         default:
8720                         wstatus = WERR_UNKNOWN_LEVEL;
8721                         break;
8722         }
8723         
8724         SAFE_FREE(queue);
8725         free_a_printer( &ntprinter, 2 );
8726         
8727         return wstatus;
8728 }
8729
8730 /********************************************************************
8731  spoolss_getprinterdataex
8732  
8733  From MSDN documentation of GetPrinterDataEx: pass request
8734  to GetPrinterData if key is "PrinterDriverData".
8735  ********************************************************************/
8736
8737 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8738 {
8739         POLICY_HND      *handle = &q_u->handle;
8740         uint32          in_size = q_u->size;
8741         uint32          *type = &r_u->type;
8742         uint32          *out_size = &r_u->size;
8743         uint8           **data = &r_u->data;
8744         uint32          *needed = &r_u->needed;
8745         fstring         keyname, valuename;
8746         
8747         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8748         
8749         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8750         int                     snum = 0;
8751         WERROR                  status = WERR_OK;
8752
8753         DEBUG(4,("_spoolss_getprinterdataex\n"));
8754
8755         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8756         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8757         
8758         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
8759                 keyname, valuename));
8760
8761         /* in case of problem, return some default values */
8762         
8763         *needed   = 0;
8764         *type     = 0;
8765         *out_size = in_size;
8766
8767         if (!Printer) {
8768                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8769                 status = WERR_BADFID;
8770                 goto done;
8771         }
8772
8773         /* Is the handle to a printer or to the server? */
8774
8775         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8776                 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8777                 status = WERR_INVALID_PARAM;
8778                 goto done;
8779         }
8780         
8781         if ( !get_printer_snum(p,handle, &snum) )
8782                 return WERR_BADFID;
8783
8784         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8785         if ( !W_ERROR_IS_OK(status) )
8786                 goto done;
8787
8788         /* check to see if the keyname is valid */
8789         if ( !strlen(keyname) ) {
8790                 status = WERR_INVALID_PARAM;
8791                 goto done;
8792         }
8793         
8794         if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8795                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8796                 free_a_printer( &printer, 2 );
8797                 status = WERR_BADFILE;
8798                 goto done;
8799         }
8800         
8801         /* When given a new keyname, we should just create it */
8802
8803         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8804         
8805         if (*needed > *out_size)
8806                 status = WERR_MORE_DATA;
8807
8808 done:
8809         if ( !W_ERROR_IS_OK(status) ) 
8810         {
8811                 DEBUG(5, ("error: allocating %d\n", *out_size));
8812                 
8813                 /* reply this param doesn't exist */
8814                 
8815                 if ( *out_size ) 
8816                 {
8817                         if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8818                                 status = WERR_NOMEM;
8819                                 goto done;
8820                         }
8821                 } 
8822                 else {
8823                         *data = NULL;
8824         }
8825         }
8826         
8827         if ( printer )
8828         free_a_printer( &printer, 2 );
8829         
8830         return status;
8831 }
8832
8833 /********************************************************************
8834  * spoolss_setprinterdataex
8835  ********************************************************************/
8836
8837 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8838 {
8839         POLICY_HND              *handle = &q_u->handle; 
8840         uint32                  type = q_u->type;
8841         uint8                   *data = q_u->data;
8842         uint32                  real_len = q_u->real_len;
8843
8844         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8845         int                     snum = 0;
8846         WERROR                  status = WERR_OK;
8847         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
8848         fstring                 valuename;
8849         fstring                 keyname;
8850         char                    *oid_string;
8851         
8852         DEBUG(4,("_spoolss_setprinterdataex\n"));
8853
8854         /* From MSDN documentation of SetPrinterDataEx: pass request to
8855            SetPrinterData if key is "PrinterDriverData" */
8856
8857         if (!Printer) {
8858                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8859                 return WERR_BADFID;
8860         }
8861
8862         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8863                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8864                 return WERR_INVALID_PARAM;
8865         }
8866
8867         if ( !get_printer_snum(p,handle, &snum) )
8868                 return WERR_BADFID;
8869
8870         /* 
8871          * Access check : NT returns "access denied" if you make a 
8872          * SetPrinterData call without the necessary privildge.
8873          * we were originally returning OK if nothing changed
8874          * which made Win2k issue **a lot** of SetPrinterData
8875          * when connecting to a printer  --jerry
8876          */
8877
8878         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8879         {
8880                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8881                 return WERR_ACCESS_DENIED;
8882         }
8883
8884         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8885         if (!W_ERROR_IS_OK(status))
8886                 return status;
8887
8888         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8889         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8890         
8891         /* check for OID in valuename */
8892         
8893         if ( (oid_string = strchr( valuename, ',' )) != NULL )
8894         {
8895                 *oid_string = '\0';
8896                 oid_string++;
8897         }
8898
8899         /* save the registry data */
8900         
8901         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
8902         
8903         if ( W_ERROR_IS_OK(status) )
8904         {
8905                 /* save the OID if one was specified */
8906                 if ( oid_string ) {
8907                         fstrcat( keyname, "\\" );
8908                         fstrcat( keyname, SPOOL_OID_KEY );
8909                 
8910                         /* 
8911                          * I'm not checking the status here on purpose.  Don't know 
8912                          * if this is right, but I'm returning the status from the 
8913                          * previous set_printer_dataex() call.  I have no idea if 
8914                          * this is right.    --jerry
8915                          */
8916                  
8917                         set_printer_dataex( printer, keyname, valuename, 
8918                                             REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
8919                 }
8920         
8921                 status = mod_a_printer(printer, 2);
8922         }
8923                 
8924         free_a_printer(&printer, 2);
8925
8926         return status;
8927 }
8928
8929
8930 /********************************************************************
8931  * spoolss_deleteprinterdataex
8932  ********************************************************************/
8933
8934 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8935 {
8936         POLICY_HND      *handle = &q_u->handle;
8937         UNISTR2         *value = &q_u->valuename;
8938         UNISTR2         *key = &q_u->keyname;
8939
8940         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8941         int             snum=0;
8942         WERROR          status = WERR_OK;
8943         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8944         pstring         valuename, keyname;
8945         
8946         DEBUG(5,("spoolss_deleteprinterdataex\n"));
8947         
8948         if (!Printer) {
8949                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8950                 return WERR_BADFID;
8951         }
8952
8953         if (!get_printer_snum(p, handle, &snum))
8954                 return WERR_BADFID;
8955
8956         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8957                 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8958                 return WERR_ACCESS_DENIED;
8959         }
8960
8961         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8962         if (!W_ERROR_IS_OK(status))
8963                 return status;
8964
8965         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8966         unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8967
8968         status = delete_printer_dataex( printer, keyname, valuename );
8969
8970         if ( W_ERROR_IS_OK(status) )
8971                 mod_a_printer( printer, 2 );
8972                 
8973         free_a_printer(&printer, 2);
8974
8975         return status;
8976 }
8977
8978 /********************************************************************
8979  * spoolss_enumprinterkey
8980  ********************************************************************/
8981
8982
8983 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8984 {
8985         fstring         key;
8986         fstring         *keynames = NULL;
8987         uint16          *enumkeys = NULL;
8988         int             num_keys;
8989         int             printerkey_len;
8990         POLICY_HND      *handle = &q_u->handle;
8991         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8992         NT_PRINTER_DATA *data;
8993         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8994         int             snum = 0;
8995         WERROR          status = WERR_BADFILE;
8996         
8997         
8998         DEBUG(4,("_spoolss_enumprinterkey\n"));
8999
9000         if (!Printer) {
9001                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9002                 return WERR_BADFID;
9003         }
9004
9005         if ( !get_printer_snum(p,handle, &snum) )
9006                 return WERR_BADFID;
9007
9008         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9009         if (!W_ERROR_IS_OK(status))
9010                 return status;
9011                 
9012         /* get the list of subkey names */
9013         
9014         unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9015         data = &printer->info_2->data;
9016
9017         num_keys = get_printer_subkeys( data, key, &keynames );
9018
9019         if ( num_keys == -1 ) {
9020                 status = WERR_BADFILE;
9021                 goto done;
9022         }
9023
9024         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9025
9026         r_u->needed = printerkey_len*2;
9027
9028         if ( q_u->size < r_u->needed ) {
9029                 status = WERR_MORE_DATA;
9030                 goto done;
9031         }
9032
9033         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9034                 status = WERR_NOMEM;
9035                 goto done;
9036         }
9037                         
9038         status = WERR_OK;
9039
9040         if ( q_u->size < r_u->needed ) 
9041                 status = WERR_MORE_DATA;
9042
9043 done:
9044         free_a_printer( &printer, 2 );
9045         SAFE_FREE( keynames );
9046         
9047         return status;
9048 }
9049
9050 /********************************************************************
9051  * spoolss_deleteprinterkey
9052  ********************************************************************/
9053
9054 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9055 {
9056         POLICY_HND              *handle = &q_u->handle;
9057         Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9058         fstring                 key;
9059         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9060         int                     snum=0;
9061         WERROR                  status;
9062         
9063         DEBUG(5,("spoolss_deleteprinterkey\n"));
9064         
9065         if (!Printer) {
9066                 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9067                 return WERR_BADFID;
9068         }
9069
9070         /* if keyname == NULL, return error */
9071         
9072         if ( !q_u->keyname.buffer )
9073                 return WERR_INVALID_PARAM;
9074                 
9075         if (!get_printer_snum(p, handle, &snum))
9076                 return WERR_BADFID;
9077
9078         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9079                 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9080                 return WERR_ACCESS_DENIED;
9081         }
9082
9083         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9084         if (!W_ERROR_IS_OK(status))
9085                 return status;
9086         
9087         /* delete the key and all subneys */
9088         
9089         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9090  
9091         status = delete_all_printer_data( printer->info_2, key );       
9092
9093         if ( W_ERROR_IS_OK(status) )
9094                 status = mod_a_printer(printer, 2);
9095         
9096         free_a_printer( &printer, 2 );
9097         
9098         return status;
9099 }
9100
9101
9102 /********************************************************************
9103  * spoolss_enumprinterdataex
9104  ********************************************************************/
9105
9106 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9107 {
9108         POLICY_HND      *handle = &q_u->handle; 
9109         uint32          in_size = q_u->size;
9110         uint32          num_entries, 
9111                         needed;
9112         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9113         PRINTER_ENUM_VALUES     *enum_values = NULL;
9114         NT_PRINTER_DATA         *p_data;
9115         fstring         key;
9116         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9117         int             snum;
9118         WERROR          result;
9119         int             key_index;
9120         int             i;
9121         REGISTRY_VALUE  *val;
9122         char            *value_name;
9123         int             data_len;
9124         
9125
9126         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9127
9128         if (!Printer) {
9129                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9130                 return WERR_BADFID;
9131         }
9132
9133         /* 
9134          * first check for a keyname of NULL or "".  Win2k seems to send 
9135          * this a lot and we should send back WERR_INVALID_PARAM
9136          * no need to spend time looking up the printer in this case.
9137          * --jerry
9138          */
9139          
9140         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9141         if ( !strlen(key) ) {
9142                 result = WERR_INVALID_PARAM;
9143                 goto done;
9144         }
9145
9146         /* get the printer off of disk */
9147         
9148         if (!get_printer_snum(p,handle, &snum))
9149                 return WERR_BADFID;
9150         
9151         ZERO_STRUCT(printer);
9152         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9153         if (!W_ERROR_IS_OK(result))
9154                 return result;
9155         
9156         /* now look for a match on the key name */
9157         
9158         p_data = &printer->info_2->data;
9159         
9160         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9161         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9162         {
9163                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9164                 result = WERR_INVALID_PARAM;
9165                 goto done;
9166         }
9167         
9168         result = WERR_OK;
9169         needed = 0;
9170         
9171         /* allocate the memory for the array of pointers -- if necessary */
9172         
9173         num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9174         if ( num_entries )
9175         {
9176                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9177                 {
9178                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9179                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9180                         result = WERR_NOMEM;
9181                         goto done;
9182                 }
9183
9184                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9185         }
9186                 
9187         /* 
9188          * loop through all params and build the array to pass 
9189          * back to the  client 
9190          */
9191          
9192         for ( i=0; i<num_entries; i++ )
9193         {
9194                 /* lookup the registry value */
9195                 
9196                 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9197                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9198
9199                 /* copy the data */
9200                 
9201                 value_name = regval_name( val );
9202                 init_unistr( &enum_values[i].valuename, value_name );
9203                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9204                 enum_values[i].type      = regval_type( val );
9205                 
9206                 data_len = regval_size( val );
9207                 if ( data_len ) {
9208                         if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) ) 
9209                         {
9210                                 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", 
9211                                         data_len ));
9212                                 result = WERR_NOMEM;
9213                                 goto done;
9214                         }
9215                 }
9216                 enum_values[i].data_len = data_len;
9217
9218                 /* keep track of the size of the array in bytes */
9219                 
9220                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9221         }
9222         
9223         /* housekeeping information in the reply */
9224         
9225         r_u->needed     = needed;
9226         r_u->returned   = num_entries;
9227
9228         if (needed > in_size) {
9229                 result = WERR_MORE_DATA;
9230                 goto done;
9231         }
9232                 
9233         /* copy data into the reply */
9234         
9235         r_u->ctr.size           = r_u->needed;
9236         r_u->ctr.size_of_array  = r_u->returned;
9237         r_u->ctr.values         = enum_values;
9238         
9239         
9240                 
9241 done:   
9242         if ( printer )
9243         free_a_printer(&printer, 2);
9244
9245         return result;
9246 }
9247
9248 /****************************************************************************
9249 ****************************************************************************/
9250
9251 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9252 {
9253         init_unistr(&info->name, name);
9254 }
9255
9256 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
9257                                                  UNISTR2 *environment, 
9258                                                  NEW_BUFFER *buffer, 
9259                                                  uint32 offered, 
9260                                                  uint32 *needed)
9261 {
9262         pstring path;
9263         pstring long_archi;
9264         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9265
9266         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9267
9268         if (!get_short_archi(long_archi))
9269                 return WERR_INVALID_ENVIRONMENT;
9270
9271         if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9272                 return WERR_NOMEM;
9273
9274         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9275
9276         fill_printprocessordirectory_1(info, path);
9277         
9278         *needed += spoolss_size_printprocessordirectory_info_1(info);
9279
9280         if (!alloc_buffer_size(buffer, *needed)) {
9281                 safe_free(info);
9282                 return WERR_INSUFFICIENT_BUFFER;
9283         }
9284
9285         smb_io_printprocessordirectory_1("", buffer, info, 0);
9286
9287         safe_free(info);
9288         
9289         if (*needed > offered)
9290                 return WERR_INSUFFICIENT_BUFFER;
9291         else
9292                 return WERR_OK;
9293 }
9294
9295 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9296 {
9297         uint32 level = q_u->level;
9298         NEW_BUFFER *buffer = NULL;
9299         uint32 offered = q_u->offered;
9300         uint32 *needed = &r_u->needed;
9301         WERROR result;
9302
9303         /* that's an [in out] buffer */
9304         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9305         buffer = r_u->buffer;
9306
9307         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9308         
9309         *needed=0;
9310
9311         switch(level) {
9312         case 1:
9313                 result = getprintprocessordirectory_level_1
9314                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9315                 break;
9316         default:
9317                 result = WERR_UNKNOWN_LEVEL;
9318         }
9319
9320         return result;
9321 }
9322
9323 #if 0
9324
9325 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u, 
9326                                  SPOOL_R_REPLYOPENPRINTER *r_u)
9327 {
9328         DEBUG(5,("_spoolss_replyopenprinter\n"));
9329
9330         DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9331
9332         return WERR_OK;
9333 }
9334
9335 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u, 
9336                                   SPOOL_R_REPLYCLOSEPRINTER *r_u)
9337 {
9338         DEBUG(5,("_spoolss_replycloseprinter\n"));
9339         return WERR_OK;
9340 }
9341
9342 #endif