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