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