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