r1241: Fix incorrect type in printer publishing (struct uuid, not UUID_FLAT).
[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         for (i=0; i<option->count; i++) {
3729                 option_type=&(option->ctr.type[i]);
3730                 
3731                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3732                         continue;
3733                 
3734                 for (snum=0; snum<n_services; snum++)
3735                 {
3736                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3737                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3738                 }
3739         }
3740                         
3741 #if 0                   
3742         /*
3743          * Debugging information, don't delete.
3744          */
3745
3746         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3747         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3748         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3749         
3750         for (i=0; i<info->count; i++) {
3751                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3752                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3753                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3754         }
3755 #endif
3756         
3757         return WERR_OK;
3758 }
3759
3760 /*******************************************************************
3761  *
3762  * fill a notify_info struct with info asked
3763  *
3764  ********************************************************************/
3765
3766 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3767                                   TALLOC_CTX *mem_ctx)
3768 {
3769         int snum;
3770         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3771         int i;
3772         uint32 id;
3773         SPOOL_NOTIFY_OPTION *option;
3774         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3775         int count,j;
3776         print_queue_struct *queue=NULL;
3777         print_status_struct status;
3778         
3779         DEBUG(4,("printer_notify_info\n"));
3780
3781         if (!Printer)
3782                 return WERR_BADFID;
3783
3784         option=Printer->notify.option;
3785         id = 0x0;
3786         info->version=2;
3787         info->data=NULL;
3788         info->count=0;
3789
3790         get_printer_snum(p, hnd, &snum);
3791
3792         for (i=0; i<option->count; i++) {
3793                 option_type=&option->ctr.type[i];
3794                 
3795                 switch ( option_type->type ) {
3796                 case PRINTER_NOTIFY_TYPE:
3797                         if(construct_notify_printer_info(Printer, info, snum, 
3798                                                          option_type, id,
3799                                                          mem_ctx))  
3800                                 id--;
3801                         break;
3802                         
3803                 case JOB_NOTIFY_TYPE: {
3804                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3805
3806                         count = print_queue_status(snum, &queue, &status);
3807
3808                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3809                                 goto done;
3810
3811                         for (j=0; j<count; j++) {
3812                                 construct_notify_jobs_info(&queue[j], info,
3813                                                            printer, snum,
3814                                                            option_type,
3815                                                            queue[j].job,
3816                                                            mem_ctx); 
3817                         }
3818
3819                         free_a_printer(&printer, 2);
3820                         
3821                 done:
3822                         SAFE_FREE(queue);
3823                         break;
3824                 }
3825                 }
3826         }
3827         
3828         /*
3829          * Debugging information, don't delete.
3830          */
3831         /*
3832         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3833         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3834         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3835         
3836         for (i=0; i<info->count; i++) {
3837                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3838                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3839                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3840         }
3841         */
3842         return WERR_OK;
3843 }
3844
3845 /********************************************************************
3846  * spoolss_rfnpcnex
3847  ********************************************************************/
3848
3849 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3850 {
3851         POLICY_HND *handle = &q_u->handle;
3852         SPOOL_NOTIFY_INFO *info = &r_u->info;
3853
3854         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3855         WERROR result = WERR_BADFID;
3856
3857         /* we always have a NOTIFY_INFO struct */
3858         r_u->info_ptr=0x1;
3859
3860         if (!Printer) {
3861                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3862                          OUR_HANDLE(handle)));
3863                 goto done;
3864         }
3865
3866         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3867
3868         /*
3869          *      We are now using the change value, and 
3870          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3871          *      I don't have a global notification system, I'm sending back all the
3872          *      informations even when _NOTHING_ has changed.
3873          */
3874
3875         /* We need to keep track of the change value to send back in 
3876            RRPCN replies otherwise our updates are ignored. */
3877
3878         Printer->notify.fnpcn = True;
3879
3880         if (Printer->notify.client_connected) {
3881                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3882                 Printer->notify.change = q_u->change;
3883         }
3884
3885         /* just ignore the SPOOL_NOTIFY_OPTION */
3886         
3887         switch (Printer->printer_type) {
3888                 case PRINTER_HANDLE_IS_PRINTSERVER:
3889                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3890                         break;
3891                         
3892                 case PRINTER_HANDLE_IS_PRINTER:
3893                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3894                         break;
3895         }
3896         
3897         Printer->notify.fnpcn = False;
3898         
3899 done:
3900         return result;
3901 }
3902
3903 /********************************************************************
3904  * construct_printer_info_0
3905  * fill a printer_info_0 struct
3906  ********************************************************************/
3907
3908 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3909 {
3910         pstring chaine;
3911         int count;
3912         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3913         counter_printer_0 *session_counter;
3914         uint32 global_counter;
3915         struct tm *t;
3916         time_t setuptime;
3917         print_status_struct status;
3918         
3919         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3920                 return False;
3921
3922         count = print_queue_length(snum, &status);
3923
3924         /* check if we already have a counter for this printer */       
3925         session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
3926
3927         for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
3928                 if (session_counter->snum == snum)
3929                         break;
3930         }
3931
3932         /* it's the first time, add it to the list */
3933         if (session_counter==NULL) {
3934                 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
3935                         free_a_printer(&ntprinter, 2);
3936                         return False;
3937                 }
3938                 ZERO_STRUCTP(session_counter);
3939                 session_counter->snum=snum;
3940                 session_counter->counter=0;
3941                 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
3942         }
3943         
3944         /* increment it */
3945         session_counter->counter++;
3946         
3947         /* JFM:
3948          * the global_counter should be stored in a TDB as it's common to all the clients
3949          * and should be zeroed on samba startup
3950          */
3951         global_counter=session_counter->counter;
3952         
3953         pstrcpy(chaine,ntprinter->info_2->printername);
3954
3955         init_unistr(&printer->printername, chaine);
3956         
3957         slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_called_name());
3958         init_unistr(&printer->servername, chaine);
3959         
3960         printer->cjobs = count;
3961         printer->total_jobs = 0;
3962         printer->total_bytes = 0;
3963
3964         setuptime = (time_t)ntprinter->info_2->setuptime;
3965         t=gmtime(&setuptime);
3966
3967         printer->year = t->tm_year+1900;
3968         printer->month = t->tm_mon+1;
3969         printer->dayofweek = t->tm_wday;
3970         printer->day = t->tm_mday;
3971         printer->hour = t->tm_hour;
3972         printer->minute = t->tm_min;
3973         printer->second = t->tm_sec;
3974         printer->milliseconds = 0;
3975
3976         printer->global_counter = global_counter;
3977         printer->total_pages = 0;
3978         
3979         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3980         printer->major_version = 0x0005;        /* NT 5 */
3981         printer->build_version = 0x0893;        /* build 2195 */
3982         
3983         printer->unknown7 = 0x1;
3984         printer->unknown8 = 0x0;
3985         printer->unknown9 = 0x0;
3986         printer->session_counter = session_counter->counter;
3987         printer->unknown11 = 0x0;
3988         printer->printer_errors = 0x0;          /* number of print failure */
3989         printer->unknown13 = 0x0;
3990         printer->unknown14 = 0x1;
3991         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3992         printer->unknown16 =  0x0;
3993         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3994         printer->unknown18 =  0x0;
3995         printer->status = nt_printq_status(status.status);
3996         printer->unknown20 =  0x0;
3997         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3998         printer->unknown22 = 0x0;
3999         printer->unknown23 = 0x6;               /* 6  ???*/
4000         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
4001         printer->unknown25 = 0;
4002         printer->unknown26 = 0;
4003         printer->unknown27 = 0;
4004         printer->unknown28 = 0;
4005         printer->unknown29 = 0;
4006         
4007         free_a_printer(&ntprinter,2);
4008         return (True);  
4009 }
4010
4011 /********************************************************************
4012  * construct_printer_info_1
4013  * fill a printer_info_1 struct
4014  ********************************************************************/
4015 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4016 {
4017         pstring chaine;
4018         pstring chaine2;
4019         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4020
4021         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4022                 return False;
4023
4024         printer->flags=flags;
4025
4026         if (*ntprinter->info_2->comment == '\0') {
4027                 init_unistr(&printer->comment, lp_comment(snum));
4028                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4029                         ntprinter->info_2->drivername, lp_comment(snum));
4030         }
4031         else {
4032                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4033                 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4034                         ntprinter->info_2->drivername, ntprinter->info_2->comment);
4035         }
4036                 
4037         slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4038
4039         init_unistr(&printer->description, chaine);
4040         init_unistr(&printer->name, chaine2);   
4041         
4042         free_a_printer(&ntprinter,2);
4043
4044         return True;
4045 }
4046
4047 /****************************************************************************
4048  Free a DEVMODE struct.
4049 ****************************************************************************/
4050
4051 static void free_dev_mode(DEVICEMODE *dev)
4052 {
4053         if (dev == NULL)
4054                 return;
4055
4056                 SAFE_FREE(dev->private);
4057         SAFE_FREE(dev); 
4058 }
4059
4060
4061 /****************************************************************************
4062  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers 
4063  should be valid upon entry
4064 ****************************************************************************/
4065
4066 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4067 {
4068         if ( !devmode || !ntdevmode )
4069                 return False;
4070                 
4071         init_unistr(&devmode->devicename, ntdevmode->devicename);
4072
4073         init_unistr(&devmode->formname, ntdevmode->formname);
4074
4075         devmode->specversion      = ntdevmode->specversion;
4076         devmode->driverversion    = ntdevmode->driverversion;
4077         devmode->size             = ntdevmode->size;
4078         devmode->driverextra      = ntdevmode->driverextra;
4079         devmode->fields           = ntdevmode->fields;
4080                                 
4081         devmode->orientation      = ntdevmode->orientation;     
4082         devmode->papersize        = ntdevmode->papersize;
4083         devmode->paperlength      = ntdevmode->paperlength;
4084         devmode->paperwidth       = ntdevmode->paperwidth;
4085         devmode->scale            = ntdevmode->scale;
4086         devmode->copies           = ntdevmode->copies;
4087         devmode->defaultsource    = ntdevmode->defaultsource;
4088         devmode->printquality     = ntdevmode->printquality;
4089         devmode->color            = ntdevmode->color;
4090         devmode->duplex           = ntdevmode->duplex;
4091         devmode->yresolution      = ntdevmode->yresolution;
4092         devmode->ttoption         = ntdevmode->ttoption;
4093         devmode->collate          = ntdevmode->collate;
4094         devmode->icmmethod        = ntdevmode->icmmethod;
4095         devmode->icmintent        = ntdevmode->icmintent;
4096         devmode->mediatype        = ntdevmode->mediatype;
4097         devmode->dithertype       = ntdevmode->dithertype;
4098
4099         if (ntdevmode->private != NULL) {
4100                 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4101                         return False;
4102         }
4103         
4104         return True;
4105 }
4106
4107 /****************************************************************************
4108  Create a DEVMODE struct. Returns malloced memory.
4109 ****************************************************************************/
4110
4111 DEVICEMODE *construct_dev_mode(int snum)
4112 {
4113         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4114         DEVICEMODE              *devmode = NULL;
4115         
4116         DEBUG(7,("construct_dev_mode\n"));
4117         
4118         DEBUGADD(8,("getting printer characteristics\n"));
4119
4120         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) 
4121                 return NULL;
4122
4123         if ( !printer->info_2->devmode ) {
4124                 DEBUG(5, ("BONG! There was no device mode!\n"));
4125                 goto done;
4126         }
4127
4128         if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
4129                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4130                 goto done;
4131         }
4132
4133         ZERO_STRUCTP(devmode);  
4134         
4135         DEBUGADD(8,("loading DEVICEMODE\n"));
4136
4137         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4138                 free_dev_mode( devmode );
4139                 devmode = NULL;
4140         }
4141
4142 done:
4143         free_a_printer(&printer,2);
4144
4145         return devmode;
4146 }
4147
4148 /********************************************************************
4149  * construct_printer_info_2
4150  * fill a printer_info_2 struct
4151  ********************************************************************/
4152
4153 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4154 {
4155         int count;
4156         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4157
4158         print_status_struct status;
4159
4160         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4161                 return False;
4162                 
4163         count = print_queue_length(snum, &status);
4164
4165         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4166         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4167         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4168         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */      
4169         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4170
4171         if (*ntprinter->info_2->comment == '\0')
4172                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */   
4173         else
4174                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4175
4176         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */  
4177         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4178         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4179         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */  
4180         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */   
4181
4182         printer->attributes = ntprinter->info_2->attributes;
4183
4184         printer->priority = ntprinter->info_2->priority;                                /* priority */  
4185         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4186         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4187         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4188         printer->status = nt_printq_status(status.status);                      /* status */
4189         printer->cjobs = count;                                                 /* jobs */
4190         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4191                         
4192         if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4193                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4194         }
4195
4196         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4197                 /* steal the printer info sec_desc structure.  [badly done]. */
4198                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4199                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4200                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4201                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4202         }
4203         else {
4204                 printer->secdesc = NULL;
4205         }
4206
4207         free_a_printer(&ntprinter, 2);
4208         return True;
4209 }
4210
4211 /********************************************************************
4212  * construct_printer_info_3
4213  * fill a printer_info_3 struct
4214  ********************************************************************/
4215
4216 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4217 {
4218         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4219         PRINTER_INFO_3 *printer = NULL;
4220
4221         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4222                 return False;
4223
4224         *pp_printer = NULL;
4225         if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
4226                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4227                 return False;
4228         }
4229
4230         ZERO_STRUCTP(printer);
4231         
4232         printer->flags = 4; /* These are the components of the SD we are returning. */
4233         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4234                 /* steal the printer info sec_desc structure.  [badly done]. */
4235                 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4236
4237 #if 0
4238                 /*
4239                  * Set the flags for the components we are returning.
4240                  */
4241
4242                 if (printer->secdesc->owner_sid)
4243                         printer->flags |= OWNER_SECURITY_INFORMATION;
4244
4245                 if (printer->secdesc->grp_sid)
4246                         printer->flags |= GROUP_SECURITY_INFORMATION;
4247
4248                 if (printer->secdesc->dacl)
4249                         printer->flags |= DACL_SECURITY_INFORMATION;
4250
4251                 if (printer->secdesc->sacl)
4252                         printer->flags |= SACL_SECURITY_INFORMATION;
4253 #endif
4254
4255                 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4256                 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4257                 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4258         }
4259
4260         free_a_printer(&ntprinter, 2);
4261
4262         *pp_printer = printer;
4263         return True;
4264 }
4265
4266 /********************************************************************
4267  * construct_printer_info_4
4268  * fill a printer_info_4 struct
4269  ********************************************************************/
4270
4271 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4272 {
4273         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4274
4275         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4276                 return False;
4277                 
4278         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4279         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4280         printer->attributes = ntprinter->info_2->attributes;
4281
4282         free_a_printer(&ntprinter, 2);
4283         return True;
4284 }
4285
4286 /********************************************************************
4287  * construct_printer_info_5
4288  * fill a printer_info_5 struct
4289  ********************************************************************/
4290
4291 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4292 {
4293         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4294
4295         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4296                 return False;
4297                 
4298         init_unistr(&printer->printername, ntprinter->info_2->printername);
4299         init_unistr(&printer->portname, ntprinter->info_2->portname); 
4300         printer->attributes = ntprinter->info_2->attributes;
4301
4302         /* these two are not used by NT+ according to MSDN */
4303
4304         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4305         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4306
4307         free_a_printer(&ntprinter, 2);
4308
4309         return True;
4310 }
4311
4312 /********************************************************************
4313  * construct_printer_info_7
4314  * fill a printer_info_7 struct
4315  ********************************************************************/
4316
4317 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4318 {
4319         char *guid_str = NULL;
4320         struct uuid guid; 
4321         
4322         if (is_printer_published(print_hnd, snum, &guid)) {
4323                 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4324                 strupper_m(guid_str);
4325                 init_unistr(&printer->guid, guid_str);
4326                 printer->action = SPOOL_DS_PUBLISH;
4327         } else {
4328                 init_unistr(&printer->guid, "");
4329                 printer->action = SPOOL_DS_UNPUBLISH;
4330         }
4331
4332         return True;
4333 }
4334
4335 /********************************************************************
4336  Spoolss_enumprinters.
4337 ********************************************************************/
4338
4339 static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4340 {
4341         int snum;
4342         int i;
4343         int n_services=lp_numservices();
4344         PRINTER_INFO_1 *tp, *printers=NULL;
4345         PRINTER_INFO_1 current_prt;
4346         
4347         DEBUG(4,("enum_all_printers_info_1\n"));        
4348
4349         for (snum=0; snum<n_services; snum++) {
4350                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4351                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4352
4353                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4354                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
4355                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4356                                         SAFE_FREE(printers);
4357                                         *returned=0;
4358                                         return WERR_NOMEM;
4359                                 }
4360                                 else printers = tp;
4361                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));             
4362
4363                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4364                                 (*returned)++;
4365                         }
4366                 }
4367         }
4368                 
4369         /* check the required size. */  
4370         for (i=0; i<*returned; i++)
4371                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4372
4373         if (!alloc_buffer_size(buffer, *needed))
4374                 return WERR_INSUFFICIENT_BUFFER;
4375
4376         /* fill the buffer with the structures */
4377         for (i=0; i<*returned; i++)
4378                 smb_io_printer_info_1("", buffer, &printers[i], 0);     
4379
4380         /* clear memory */
4381         SAFE_FREE(printers);
4382
4383         if (*needed > offered) {
4384                 *returned=0;
4385                 return WERR_INSUFFICIENT_BUFFER;
4386         }
4387         else
4388                 return WERR_OK;
4389 }
4390
4391 /********************************************************************
4392  enum_all_printers_info_1_local.
4393 *********************************************************************/
4394
4395 static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4396 {
4397         DEBUG(4,("enum_all_printers_info_1_local\n"));  
4398         
4399         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4400 }
4401
4402 /********************************************************************
4403  enum_all_printers_info_1_name.
4404 *********************************************************************/
4405
4406 static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4407 {
4408         char *s = name;
4409         
4410         DEBUG(4,("enum_all_printers_info_1_name\n"));   
4411         
4412         if ((name[0] == '\\') && (name[1] == '\\'))
4413                 s = name + 2;
4414                 
4415         if (is_myname_or_ipaddr(s)) {
4416                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4417         }
4418         else
4419                 return WERR_INVALID_NAME;
4420 }
4421
4422 /********************************************************************
4423  enum_all_printers_info_1_remote.
4424 *********************************************************************/
4425
4426 static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4427 {
4428         PRINTER_INFO_1 *printer;
4429         fstring printername;
4430         fstring desc;
4431         fstring comment;
4432         DEBUG(4,("enum_all_printers_info_1_remote\n")); 
4433
4434         /* JFM: currently it's more a place holder than anything else.
4435          * In the spooler world there is a notion of server registration.
4436          * the print servers are registring (sp ?) on the PDC (in the same domain)
4437          *
4438          * We should have a TDB here. The registration is done thru an undocumented RPC call.
4439          */
4440         
4441         if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4442                 return WERR_NOMEM;
4443
4444         *returned=1;
4445         
4446         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());           
4447         slprintf(desc, sizeof(desc)-1,"%s", get_called_name());
4448         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4449
4450         init_unistr(&printer->description, desc);
4451         init_unistr(&printer->name, printername);       
4452         init_unistr(&printer->comment, comment);
4453         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4454                 
4455         /* check the required size. */  
4456         *needed += spoolss_size_printer_info_1(printer);
4457
4458         if (!alloc_buffer_size(buffer, *needed)) {
4459                 SAFE_FREE(printer);
4460                 return WERR_INSUFFICIENT_BUFFER;
4461         }
4462
4463         /* fill the buffer with the structures */
4464         smb_io_printer_info_1("", buffer, printer, 0);  
4465
4466         /* clear memory */
4467         SAFE_FREE(printer);
4468
4469         if (*needed > offered) {
4470                 *returned=0;
4471                 return WERR_INSUFFICIENT_BUFFER;
4472         }
4473         else
4474                 return WERR_OK;
4475 }
4476
4477 /********************************************************************
4478  enum_all_printers_info_1_network.
4479 *********************************************************************/
4480
4481 static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4482 {
4483         char *s = name;
4484
4485         DEBUG(4,("enum_all_printers_info_1_network\n"));        
4486         
4487         /* If we respond to a enum_printers level 1 on our name with flags
4488            set to PRINTER_ENUM_REMOTE with a list of printers then these
4489            printers incorrectly appear in the APW browse list.
4490            Specifically the printers for the server appear at the workgroup
4491            level where all the other servers in the domain are
4492            listed. Windows responds to this call with a
4493            WERR_CAN_NOT_COMPLETE so we should do the same. */ 
4494
4495         if (name[0] == '\\' && name[1] == '\\')
4496                  s = name + 2;
4497
4498         if (is_myname_or_ipaddr(s))
4499                  return WERR_CAN_NOT_COMPLETE;
4500
4501         return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4502 }
4503
4504 /********************************************************************
4505  * api_spoolss_enumprinters
4506  *
4507  * called from api_spoolss_enumprinters (see this to understand)
4508  ********************************************************************/
4509
4510 static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4511 {
4512         int snum;
4513         int i;
4514         int n_services=lp_numservices();
4515         PRINTER_INFO_2 *tp, *printers=NULL;
4516         PRINTER_INFO_2 current_prt;
4517
4518         for (snum=0; snum<n_services; snum++) {
4519                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4520                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4521                                 
4522                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4523                                 if((tp=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL) {
4524                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4525                                         SAFE_FREE(printers);
4526                                         *returned = 0;
4527                                         return WERR_NOMEM;
4528                                 }
4529                                 else printers = tp;
4530                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));             
4531                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4532                                 (*returned)++;
4533                         }
4534                 }
4535         }
4536         
4537         /* check the required size. */  
4538         for (i=0; i<*returned; i++) 
4539                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4540         
4541         if (!alloc_buffer_size(buffer, *needed)) {
4542                 for (i=0; i<*returned; i++) {
4543                         free_devmode(printers[i].devmode);
4544                 }
4545                 SAFE_FREE(printers);
4546                 return WERR_INSUFFICIENT_BUFFER;
4547         }
4548
4549         /* fill the buffer with the structures */
4550         for (i=0; i<*returned; i++)
4551                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);   
4552         
4553         /* clear memory */
4554         for (i=0; i<*returned; i++) {
4555                 free_devmode(printers[i].devmode);
4556         }
4557         SAFE_FREE(printers);
4558
4559         if (*needed > offered) {
4560                 *returned=0;
4561                 return WERR_INSUFFICIENT_BUFFER;
4562         }
4563         else
4564                 return WERR_OK;
4565 }
4566
4567 /********************************************************************
4568  * handle enumeration of printers at level 1
4569  ********************************************************************/
4570
4571 static WERROR enumprinters_level1( uint32 flags, fstring name,
4572                                  NEW_BUFFER *buffer, uint32 offered,
4573                                  uint32 *needed, uint32 *returned)
4574 {
4575         /* Not all the flags are equals */
4576
4577         if (flags & PRINTER_ENUM_LOCAL)
4578                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4579
4580         if (flags & PRINTER_ENUM_NAME)
4581                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4582
4583         if (flags & PRINTER_ENUM_REMOTE)
4584                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4585
4586         if (flags & PRINTER_ENUM_NETWORK)
4587                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4588
4589         return WERR_OK; /* NT4sp5 does that */
4590 }
4591
4592 /********************************************************************
4593  * handle enumeration of printers at level 2
4594  ********************************************************************/
4595
4596 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4597                                  NEW_BUFFER *buffer, uint32 offered,
4598                                  uint32 *needed, uint32 *returned)
4599 {
4600         char *s = servername;
4601
4602         if (flags & PRINTER_ENUM_LOCAL) {
4603                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4604         }
4605
4606         if (flags & PRINTER_ENUM_NAME) {
4607                 if ((servername[0] == '\\') && (servername[1] == '\\'))
4608                         s = servername + 2;
4609                 if (is_myname_or_ipaddr(s))
4610                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4611                 else
4612                         return WERR_INVALID_NAME;
4613         }
4614
4615         if (flags & PRINTER_ENUM_REMOTE)
4616                 return WERR_UNKNOWN_LEVEL;
4617
4618         return WERR_OK;
4619 }
4620
4621 /********************************************************************
4622  * handle enumeration of printers at level 5
4623  ********************************************************************/
4624
4625 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4626                                  NEW_BUFFER *buffer, uint32 offered,
4627                                  uint32 *needed, uint32 *returned)
4628 {
4629 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4630         return WERR_OK;
4631 }
4632
4633 /********************************************************************
4634  * api_spoolss_enumprinters
4635  *
4636  * called from api_spoolss_enumprinters (see this to understand)
4637  ********************************************************************/
4638
4639 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4640 {
4641         uint32 flags = q_u->flags;
4642         UNISTR2 *servername = &q_u->servername;
4643         uint32 level = q_u->level;
4644         NEW_BUFFER *buffer = NULL;
4645         uint32 offered = q_u->offered;
4646         uint32 *needed = &r_u->needed;
4647         uint32 *returned = &r_u->returned;
4648
4649         fstring name;
4650         
4651         /* that's an [in out] buffer */
4652         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4653         buffer = r_u->buffer;
4654
4655         DEBUG(4,("_spoolss_enumprinters\n"));
4656
4657         *needed=0;
4658         *returned=0;
4659         
4660         /*
4661          * Level 1:
4662          *          flags==PRINTER_ENUM_NAME
4663          *           if name=="" then enumerates all printers
4664          *           if name!="" then enumerate the printer
4665          *          flags==PRINTER_ENUM_REMOTE
4666          *          name is NULL, enumerate printers
4667          * Level 2: name!="" enumerates printers, name can't be NULL
4668          * Level 3: doesn't exist
4669          * Level 4: does a local registry lookup
4670          * Level 5: same as Level 2
4671          */
4672
4673         unistr2_to_ascii(name, servername, sizeof(name)-1);
4674         strupper_m(name);
4675
4676         switch (level) {
4677         case 1:
4678                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4679         case 2:
4680                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4681         case 5:
4682                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4683         case 3:
4684         case 4:
4685                 break;
4686         }
4687         return WERR_UNKNOWN_LEVEL;
4688 }
4689
4690 /****************************************************************************
4691 ****************************************************************************/
4692
4693 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4694 {
4695         PRINTER_INFO_0 *printer=NULL;
4696
4697         if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
4698                 return WERR_NOMEM;
4699
4700         construct_printer_info_0(print_hnd, printer, snum);
4701         
4702         /* check the required size. */  
4703         *needed += spoolss_size_printer_info_0(printer);
4704
4705         if (!alloc_buffer_size(buffer, *needed)) {
4706                 SAFE_FREE(printer);
4707                 return WERR_INSUFFICIENT_BUFFER;
4708         }
4709
4710         /* fill the buffer with the structures */
4711         smb_io_printer_info_0("", buffer, printer, 0);  
4712         
4713         /* clear memory */
4714         SAFE_FREE(printer);
4715
4716         if (*needed > offered) {
4717                 return WERR_INSUFFICIENT_BUFFER;
4718         }
4719
4720         return WERR_OK;
4721 }
4722
4723 /****************************************************************************
4724 ****************************************************************************/
4725
4726 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4727 {
4728         PRINTER_INFO_1 *printer=NULL;
4729
4730         if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
4731                 return WERR_NOMEM;
4732
4733         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4734         
4735         /* check the required size. */  
4736         *needed += spoolss_size_printer_info_1(printer);
4737
4738         if (!alloc_buffer_size(buffer, *needed)) {
4739                 SAFE_FREE(printer);
4740                 return WERR_INSUFFICIENT_BUFFER;
4741         }
4742
4743         /* fill the buffer with the structures */
4744         smb_io_printer_info_1("", buffer, printer, 0);  
4745         
4746         /* clear memory */
4747         SAFE_FREE(printer);
4748
4749         if (*needed > offered) {
4750                 return WERR_INSUFFICIENT_BUFFER;
4751         }
4752
4753         return WERR_OK; 
4754 }
4755
4756 /****************************************************************************
4757 ****************************************************************************/
4758
4759 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4760 {
4761         PRINTER_INFO_2 *printer=NULL;
4762
4763         if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
4764                 return WERR_NOMEM;
4765         
4766         construct_printer_info_2(print_hnd, printer, snum);
4767         
4768         /* check the required size. */  
4769         *needed += spoolss_size_printer_info_2(printer);
4770         
4771         if (!alloc_buffer_size(buffer, *needed)) {
4772                 free_printer_info_2(printer);
4773                 return WERR_INSUFFICIENT_BUFFER;
4774         }
4775
4776         /* fill the buffer with the structures */
4777         if (!smb_io_printer_info_2("", buffer, printer, 0)) {
4778                 free_printer_info_2(printer);
4779                 return WERR_NOMEM;
4780         }
4781         
4782         /* clear memory */
4783         free_printer_info_2(printer);
4784
4785         if (*needed > offered) {
4786                 return WERR_INSUFFICIENT_BUFFER;
4787         }
4788
4789         return WERR_OK; 
4790 }
4791
4792 /****************************************************************************
4793 ****************************************************************************/
4794
4795 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4796 {
4797         PRINTER_INFO_3 *printer=NULL;
4798
4799         if (!construct_printer_info_3(print_hnd, &printer, snum))
4800                 return WERR_NOMEM;
4801         
4802         /* check the required size. */  
4803         *needed += spoolss_size_printer_info_3(printer);
4804
4805         if (!alloc_buffer_size(buffer, *needed)) {
4806                 free_printer_info_3(printer);
4807                 return WERR_INSUFFICIENT_BUFFER;
4808         }
4809
4810         /* fill the buffer with the structures */
4811         smb_io_printer_info_3("", buffer, printer, 0);  
4812         
4813         /* clear memory */
4814         free_printer_info_3(printer);
4815         
4816         if (*needed > offered) {
4817                 return WERR_INSUFFICIENT_BUFFER;
4818         }
4819
4820         return WERR_OK; 
4821 }
4822
4823 /****************************************************************************
4824 ****************************************************************************/
4825
4826 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4827 {
4828         PRINTER_INFO_4 *printer=NULL;
4829
4830         if((printer=(PRINTER_INFO_4*)malloc(sizeof(PRINTER_INFO_4)))==NULL)
4831                 return WERR_NOMEM;
4832
4833         if (!construct_printer_info_4(print_hnd, printer, snum))
4834                 return WERR_NOMEM;
4835         
4836         /* check the required size. */  
4837         *needed += spoolss_size_printer_info_4(printer);
4838
4839         if (!alloc_buffer_size(buffer, *needed)) {
4840                 free_printer_info_4(printer);
4841                 return WERR_INSUFFICIENT_BUFFER;
4842         }
4843
4844         /* fill the buffer with the structures */
4845         smb_io_printer_info_4("", buffer, printer, 0);  
4846         
4847         /* clear memory */
4848         free_printer_info_4(printer);
4849         
4850         if (*needed > offered) {
4851                 return WERR_INSUFFICIENT_BUFFER;
4852         }
4853
4854         return WERR_OK; 
4855 }
4856
4857 /****************************************************************************
4858 ****************************************************************************/
4859
4860 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4861 {
4862         PRINTER_INFO_5 *printer=NULL;
4863
4864         if((printer=(PRINTER_INFO_5*)malloc(sizeof(PRINTER_INFO_5)))==NULL)
4865                 return WERR_NOMEM;
4866
4867         if (!construct_printer_info_5(print_hnd, printer, snum))
4868                 return WERR_NOMEM;
4869         
4870         /* check the required size. */  
4871         *needed += spoolss_size_printer_info_5(printer);
4872
4873         if (!alloc_buffer_size(buffer, *needed)) {
4874                 free_printer_info_5(printer);
4875                 return WERR_INSUFFICIENT_BUFFER;
4876         }
4877
4878         /* fill the buffer with the structures */
4879         smb_io_printer_info_5("", buffer, printer, 0);  
4880         
4881         /* clear memory */
4882         free_printer_info_5(printer);
4883         
4884         if (*needed > offered) {
4885                 return WERR_INSUFFICIENT_BUFFER;
4886         }
4887
4888         return WERR_OK; 
4889 }
4890
4891 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4892 {
4893         PRINTER_INFO_7 *printer=NULL;
4894
4895         if((printer=(PRINTER_INFO_7*)malloc(sizeof(PRINTER_INFO_7)))==NULL)
4896                 return WERR_NOMEM;
4897
4898         if (!construct_printer_info_7(print_hnd, printer, snum))
4899                 return WERR_NOMEM;
4900         
4901         /* check the required size. */  
4902         *needed += spoolss_size_printer_info_7(printer);
4903
4904         if (!alloc_buffer_size(buffer, *needed)) {
4905                 free_printer_info_7(printer);
4906                 return WERR_INSUFFICIENT_BUFFER;
4907         }
4908
4909         /* fill the buffer with the structures */
4910         smb_io_printer_info_7("", buffer, printer, 0);  
4911         
4912         /* clear memory */
4913         free_printer_info_7(printer);
4914         
4915         if (*needed > offered) {
4916                 return WERR_INSUFFICIENT_BUFFER;
4917         }
4918
4919         return WERR_OK; 
4920 }
4921
4922 /****************************************************************************
4923 ****************************************************************************/
4924
4925 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4926 {
4927         POLICY_HND *handle = &q_u->handle;
4928         uint32 level = q_u->level;
4929         NEW_BUFFER *buffer = NULL;
4930         uint32 offered = q_u->offered;
4931         uint32 *needed = &r_u->needed;
4932         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4933
4934         int snum;
4935
4936         /* that's an [in out] buffer */
4937         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
4938         buffer = r_u->buffer;
4939
4940         *needed=0;
4941
4942         if (!get_printer_snum(p, handle, &snum))
4943                 return WERR_BADFID;
4944
4945         switch (level) {
4946         case 0:
4947                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4948         case 1:
4949                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4950         case 2:         
4951                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4952         case 3:         
4953                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4954         case 4:         
4955                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4956         case 5:         
4957                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4958         case 7:
4959                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4960         }
4961         return WERR_UNKNOWN_LEVEL;
4962 }       
4963                 
4964 /********************************************************************
4965  * fill a DRIVER_INFO_1 struct
4966  ********************************************************************/
4967
4968 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4969 {
4970         init_unistr( &info->name, driver.info_3->name);
4971 }
4972
4973 /********************************************************************
4974  * construct_printer_driver_info_1
4975  ********************************************************************/
4976
4977 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4978 {       
4979         NT_PRINTER_INFO_LEVEL *printer = NULL;
4980         NT_PRINTER_DRIVER_INFO_LEVEL driver;
4981
4982         ZERO_STRUCT(driver);
4983
4984         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4985                 return WERR_INVALID_PRINTER_NAME;
4986
4987         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4988                 return WERR_UNKNOWN_PRINTER_DRIVER;
4989
4990         fill_printer_driver_info_1(info, driver, servername, architecture);
4991
4992         free_a_printer(&printer,2);
4993
4994         return WERR_OK;
4995 }
4996
4997 /********************************************************************
4998  * construct_printer_driver_info_2
4999  * fill a printer_info_2 struct
5000  ********************************************************************/
5001
5002 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5003 {
5004         pstring temp;
5005
5006         info->version=driver.info_3->cversion;
5007
5008         init_unistr( &info->name, driver.info_3->name );
5009         init_unistr( &info->architecture, driver.info_3->environment );
5010
5011
5012     if (strlen(driver.info_3->driverpath)) {
5013                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5014                 init_unistr( &info->driverpath, temp );
5015     } else
5016         init_unistr( &info->driverpath, "" );
5017
5018         if (strlen(driver.info_3->datafile)) {
5019                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5020                 init_unistr( &info->datafile, temp );
5021         } else
5022                 init_unistr( &info->datafile, "" );
5023         
5024         if (strlen(driver.info_3->configfile)) {
5025                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5026                 init_unistr( &info->configfile, temp ); 
5027         } else
5028                 init_unistr( &info->configfile, "" );
5029 }
5030
5031 /********************************************************************
5032  * construct_printer_driver_info_2
5033  * fill a printer_info_2 struct
5034  ********************************************************************/
5035
5036 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5037 {
5038         NT_PRINTER_INFO_LEVEL *printer = NULL;
5039         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5040
5041         ZERO_STRUCT(printer);
5042         ZERO_STRUCT(driver);
5043
5044         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5045                 return WERR_INVALID_PRINTER_NAME;
5046
5047         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5048                 return WERR_UNKNOWN_PRINTER_DRIVER;
5049
5050         fill_printer_driver_info_2(info, driver, servername);
5051
5052         free_a_printer(&printer,2);
5053
5054         return WERR_OK;
5055 }
5056
5057 /********************************************************************
5058  * copy a strings array and convert to UNICODE
5059  *
5060  * convert an array of ascii string to a UNICODE string
5061  ********************************************************************/
5062
5063 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5064 {
5065         int i=0;
5066         int j=0;
5067         const char *v;
5068         pstring line;
5069         uint16 *tuary;
5070
5071         DEBUG(6,("init_unistr_array\n"));
5072         *uni_array=NULL;
5073
5074         while (True) 
5075         {
5076                 if ( !char_array )
5077                         v = "";
5078                 else 
5079                 {
5080                         v = char_array[i];
5081                         if (!v) 
5082                                 v = ""; /* hack to handle null lists */
5083                 }
5084                 
5085                 /* hack to allow this to be used in places other than when generating 
5086                    the list of dependent files */
5087                    
5088                 if ( servername )
5089                         slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5090                 else
5091                         pstrcpy( line, v );
5092                         
5093                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5094
5095                 /* add one extra unit16 for the second terminating NULL */
5096                 
5097                 if ( (tuary=Realloc(*uni_array, (j+1+strlen(line)+2)*sizeof(uint16))) == NULL ) {
5098                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5099                         return 0;
5100                 } else
5101                         *uni_array = tuary;
5102                         
5103                 if ( !strlen(v) ) 
5104                         break;
5105                 
5106                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5107                 i++;
5108         }
5109         
5110         if (*uni_array) {
5111                 /* special case for ""; we need to add both NULL's here */
5112                 if (!j)
5113                         (*uni_array)[j++]=0x0000;       
5114                 (*uni_array)[j]=0x0000;
5115         }
5116         
5117         DEBUGADD(6,("last one:done\n"));
5118
5119         /* return size of array in uint16's */
5120                 
5121         return j+1;
5122 }
5123
5124 /********************************************************************
5125  * construct_printer_info_3
5126  * fill a printer_info_3 struct
5127  ********************************************************************/
5128
5129 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5130 {
5131         pstring temp;
5132
5133         ZERO_STRUCTP(info);
5134
5135         info->version=driver.info_3->cversion;
5136
5137         init_unistr( &info->name, driver.info_3->name );        
5138         init_unistr( &info->architecture, driver.info_3->environment );
5139
5140         if (strlen(driver.info_3->driverpath)) {
5141                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5142                 init_unistr( &info->driverpath, temp );
5143         } else
5144                 init_unistr( &info->driverpath, "" );
5145     
5146         if (strlen(driver.info_3->datafile)) {
5147                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5148                 init_unistr( &info->datafile, temp );
5149         } else
5150                 init_unistr( &info->datafile, "" );
5151
5152         if (strlen(driver.info_3->configfile)) {
5153                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5154                 init_unistr( &info->configfile, temp ); 
5155         } else
5156                 init_unistr( &info->configfile, "" );
5157
5158         if (strlen(driver.info_3->helpfile)) {
5159                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5160                 init_unistr( &info->helpfile, temp );
5161         } else
5162                 init_unistr( &info->helpfile, "" );
5163
5164         init_unistr( &info->monitorname, driver.info_3->monitorname );
5165         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5166
5167         info->dependentfiles=NULL;
5168         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5169 }
5170
5171 /********************************************************************
5172  * construct_printer_info_3
5173  * fill a printer_info_3 struct
5174  ********************************************************************/
5175
5176 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5177 {       
5178         NT_PRINTER_INFO_LEVEL *printer = NULL;
5179         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5180         WERROR status;
5181         ZERO_STRUCT(driver);
5182
5183         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5184         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5185         if (!W_ERROR_IS_OK(status))
5186                 return WERR_INVALID_PRINTER_NAME;
5187
5188         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5189         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5190
5191 #if 0   /* JERRY */
5192
5193         /* 
5194          * I put this code in during testing.  Helpful when commenting out the 
5195          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5196          * as win2k always queries the driver using an infor level of 6.
5197          * I've left it in (but ifdef'd out) because I'll probably
5198          * use it in experimentation again in the future.   --jerry 22/01/2002
5199          */
5200
5201         if (!W_ERROR_IS_OK(status)) {
5202                 /*
5203                  * Is this a W2k client ?
5204                  */
5205                 if (version == 3) {
5206                         /* Yes - try again with a WinNT driver. */
5207                         version = 2;
5208                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5209                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5210                 }
5211 #endif
5212
5213                 if (!W_ERROR_IS_OK(status)) {
5214                         free_a_printer(&printer,2);
5215                         return WERR_UNKNOWN_PRINTER_DRIVER;
5216                 }
5217                 
5218 #if 0   /* JERRY */
5219         }
5220 #endif
5221         
5222
5223         fill_printer_driver_info_3(info, driver, servername);
5224
5225         free_a_printer(&printer,2);
5226
5227         return WERR_OK;
5228 }
5229
5230 /********************************************************************
5231  * construct_printer_info_6
5232  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5233  ********************************************************************/
5234
5235 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5236 {
5237         pstring temp;
5238         fstring nullstr;
5239
5240         ZERO_STRUCTP(info);
5241         memset(&nullstr, '\0', sizeof(fstring));
5242
5243         info->version=driver.info_3->cversion;
5244
5245         init_unistr( &info->name, driver.info_3->name );        
5246         init_unistr( &info->architecture, driver.info_3->environment );
5247
5248         if (strlen(driver.info_3->driverpath)) {
5249                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
5250                 init_unistr( &info->driverpath, temp );
5251         } else
5252                 init_unistr( &info->driverpath, "" );
5253
5254         if (strlen(driver.info_3->datafile)) {
5255                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5256                 init_unistr( &info->datafile, temp );
5257         } else
5258                 init_unistr( &info->datafile, "" );
5259
5260         if (strlen(driver.info_3->configfile)) {
5261                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5262                 init_unistr( &info->configfile, temp ); 
5263         } else
5264                 init_unistr( &info->configfile, "" );
5265
5266         if (strlen(driver.info_3->helpfile)) {
5267                 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5268                 init_unistr( &info->helpfile, temp );
5269         } else
5270                 init_unistr( &info->helpfile, "" );
5271         
5272         init_unistr( &info->monitorname, driver.info_3->monitorname );
5273         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5274
5275         info->dependentfiles = NULL;
5276         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5277
5278         info->previousdrivernames=NULL;
5279         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5280
5281         info->driver_date.low=0;
5282         info->driver_date.high=0;
5283
5284         info->padding=0;
5285         info->driver_version_low=0;
5286         info->driver_version_high=0;
5287
5288         init_unistr( &info->mfgname, "");
5289         init_unistr( &info->oem_url, "");
5290         init_unistr( &info->hardware_id, "");
5291         init_unistr( &info->provider, "");
5292 }
5293
5294 /********************************************************************
5295  * construct_printer_info_6
5296  * fill a printer_info_6 struct
5297  ********************************************************************/
5298
5299 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, 
5300               fstring servername, fstring architecture, uint32 version)
5301 {       
5302         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5303         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5304         WERROR                          status;
5305         
5306         ZERO_STRUCT(driver);
5307
5308         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5309         
5310         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5311         
5312         if (!W_ERROR_IS_OK(status))
5313                 return WERR_INVALID_PRINTER_NAME;
5314
5315         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5316                 
5317         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5318         
5319         if (!W_ERROR_IS_OK(status)) 
5320         {
5321                 /*
5322                  * Is this a W2k client ?
5323                  */
5324
5325                 if (version < 3) {
5326                         free_a_printer(&printer,2);
5327                         return WERR_UNKNOWN_PRINTER_DRIVER;
5328                 }
5329
5330                 /* Yes - try again with a WinNT driver. */
5331                 version = 2;
5332                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);    
5333                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5334                 if (!W_ERROR_IS_OK(status)) {
5335                         free_a_printer(&printer,2);
5336                         return WERR_UNKNOWN_PRINTER_DRIVER;
5337                 }
5338         }
5339
5340         fill_printer_driver_info_6(info, driver, servername);
5341
5342         free_a_printer(&printer,2);
5343         free_a_printer_driver(driver, 3);
5344
5345         return WERR_OK;
5346 }
5347
5348 /****************************************************************************
5349 ****************************************************************************/
5350
5351 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5352 {
5353         SAFE_FREE(info->dependentfiles);
5354 }
5355
5356 /****************************************************************************
5357 ****************************************************************************/
5358
5359 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5360 {
5361         SAFE_FREE(info->dependentfiles);
5362         
5363 }
5364
5365 /****************************************************************************
5366 ****************************************************************************/
5367
5368 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5369 {
5370         DRIVER_INFO_1 *info=NULL;
5371         WERROR status;
5372         
5373         if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
5374                 return WERR_NOMEM;
5375         
5376         status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
5377         if (!W_ERROR_IS_OK(status)) {
5378                 SAFE_FREE(info);
5379                 return status;
5380         }
5381
5382         /* check the required size. */  
5383         *needed += spoolss_size_printer_driver_info_1(info);
5384
5385         if (!alloc_buffer_size(buffer, *needed)) {
5386                 SAFE_FREE(info);
5387                 return WERR_INSUFFICIENT_BUFFER;
5388         }
5389
5390         /* fill the buffer with the structures */
5391         smb_io_printer_driver_info_1("", buffer, info, 0);      
5392
5393         /* clear memory */
5394         SAFE_FREE(info);
5395
5396         if (*needed > offered)
5397                 return WERR_INSUFFICIENT_BUFFER;
5398
5399         return WERR_OK;
5400 }
5401
5402 /****************************************************************************
5403 ****************************************************************************/
5404
5405 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5406 {
5407         DRIVER_INFO_2 *info=NULL;
5408         WERROR status;
5409         
5410         if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
5411                 return WERR_NOMEM;
5412         
5413         status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
5414         if (!W_ERROR_IS_OK(status)) {
5415                 SAFE_FREE(info);
5416                 return status;
5417         }
5418
5419         /* check the required size. */  
5420         *needed += spoolss_size_printer_driver_info_2(info);
5421
5422         if (!alloc_buffer_size(buffer, *needed)) {
5423                 SAFE_FREE(info);
5424                 return WERR_INSUFFICIENT_BUFFER;
5425         }
5426
5427         /* fill the buffer with the structures */
5428         smb_io_printer_driver_info_2("", buffer, info, 0);      
5429
5430         /* clear memory */
5431         SAFE_FREE(info);
5432
5433         if (*needed > offered)
5434                 return WERR_INSUFFICIENT_BUFFER;
5435         
5436         return WERR_OK;
5437 }
5438
5439 /****************************************************************************
5440 ****************************************************************************/
5441
5442 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5443 {
5444         DRIVER_INFO_3 info;
5445         WERROR status;
5446
5447         ZERO_STRUCT(info);
5448
5449         status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5450         if (!W_ERROR_IS_OK(status)) {
5451                 return status;
5452         }
5453
5454         /* check the required size. */  
5455         *needed += spoolss_size_printer_driver_info_3(&info);
5456
5457         if (!alloc_buffer_size(buffer, *needed)) {
5458                 free_printer_driver_info_3(&info);
5459                 return WERR_INSUFFICIENT_BUFFER;
5460         }
5461
5462         /* fill the buffer with the structures */
5463         smb_io_printer_driver_info_3("", buffer, &info, 0);
5464
5465         free_printer_driver_info_3(&info);
5466
5467         if (*needed > offered)
5468                 return WERR_INSUFFICIENT_BUFFER;
5469
5470         return WERR_OK;
5471 }
5472
5473 /****************************************************************************
5474 ****************************************************************************/
5475
5476 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
5477 {
5478         DRIVER_INFO_6 info;
5479         WERROR status;
5480
5481         ZERO_STRUCT(info);
5482
5483         status=construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5484         if (!W_ERROR_IS_OK(status)) {
5485                 return status;
5486         }
5487
5488         /* check the required size. */  
5489         *needed += spoolss_size_printer_driver_info_6(&info);
5490
5491         if (!alloc_buffer_size(buffer, *needed)) {
5492                 free_printer_driver_info_6(&info);
5493                 return WERR_INSUFFICIENT_BUFFER;
5494         }
5495
5496         /* fill the buffer with the structures */
5497         smb_io_printer_driver_info_6("", buffer, &info, 0);
5498
5499         free_printer_driver_info_6(&info);
5500
5501         if (*needed > offered)
5502                 return WERR_INSUFFICIENT_BUFFER;
5503         
5504         return WERR_OK;
5505 }
5506
5507 /****************************************************************************
5508 ****************************************************************************/
5509
5510 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5511 {
5512         POLICY_HND *handle = &q_u->handle;
5513         UNISTR2 *uni_arch = &q_u->architecture;
5514         uint32 level = q_u->level;
5515         uint32 clientmajorversion = q_u->clientmajorversion;
5516         NEW_BUFFER *buffer = NULL;
5517         uint32 offered = q_u->offered;
5518         uint32 *needed = &r_u->needed;
5519         uint32 *servermajorversion = &r_u->servermajorversion;
5520         uint32 *serverminorversion = &r_u->serverminorversion;
5521
5522         fstring servername;
5523         fstring architecture;
5524         int snum;
5525
5526         /* that's an [in out] buffer */
5527         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
5528         buffer = r_u->buffer;
5529
5530         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5531
5532         *needed = 0;
5533         *servermajorversion = 0;
5534         *serverminorversion = 0;
5535
5536         fstrcpy(servername, get_called_name());
5537         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5538
5539         if (!get_printer_snum(p, handle, &snum))
5540                 return WERR_BADFID;
5541
5542         switch (level) {
5543         case 1:
5544                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5545         case 2:
5546                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5547         case 3:
5548                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5549         case 6:
5550                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5551         }
5552
5553         return WERR_UNKNOWN_LEVEL;
5554 }
5555
5556 /****************************************************************************
5557 ****************************************************************************/
5558
5559 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5560 {
5561         POLICY_HND *handle = &q_u->handle;
5562
5563         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5564
5565         if (!Printer) {
5566                 DEBUG(3,("Error in startpageprinter printer handle\n"));
5567                 return WERR_BADFID;
5568         }
5569
5570         Printer->page_started=True;
5571         return WERR_OK;
5572 }
5573
5574 /****************************************************************************
5575 ****************************************************************************/
5576
5577 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5578 {
5579         POLICY_HND *handle = &q_u->handle;
5580         int snum;
5581
5582         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5583
5584         if (!Printer) {
5585                 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5586                 return WERR_BADFID;
5587         }
5588         
5589         if (!get_printer_snum(p, handle, &snum))
5590                 return WERR_BADFID;
5591
5592         Printer->page_started=False;
5593         print_job_endpage(snum, Printer->jobid);
5594
5595         return WERR_OK;
5596 }
5597
5598 /********************************************************************
5599  * api_spoolss_getprinter
5600  * called from the spoolss dispatcher
5601  *
5602  ********************************************************************/
5603
5604 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5605 {
5606         POLICY_HND *handle = &q_u->handle;
5607         DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5608         uint32 *jobid = &r_u->jobid;
5609
5610         DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5611         int snum;
5612         pstring jobname;
5613         fstring datatype;
5614         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615         struct current_user user;
5616
5617         if (!Printer) {
5618                 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5619                 return WERR_BADFID;
5620         }
5621
5622         get_current_user(&user, p);
5623
5624         /*
5625          * a nice thing with NT is it doesn't listen to what you tell it.
5626          * when asked to send _only_ RAW datas, it tries to send datas
5627          * in EMF format.
5628          *
5629          * So I add checks like in NT Server ...
5630          */
5631         
5632         if (info_1->p_datatype != 0) {
5633                 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5634                 if (strcmp(datatype, "RAW") != 0) {
5635                         (*jobid)=0;
5636                         return WERR_INVALID_DATATYPE;
5637                 }               
5638         }               
5639         
5640         /* get the share number of the printer */
5641         if (!get_printer_snum(p, handle, &snum)) {
5642                 return WERR_BADFID;
5643         }
5644
5645         unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5646         
5647         Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5648
5649         /* An error occured in print_job_start() so return an appropriate
5650            NT error code. */
5651
5652         if (Printer->jobid == -1) {
5653                 return map_werror_from_unix(errno);
5654         }
5655         
5656         Printer->document_started=True;
5657         (*jobid) = Printer->jobid;
5658
5659         return WERR_OK;
5660 }
5661
5662 /********************************************************************
5663  * api_spoolss_getprinter
5664  * called from the spoolss dispatcher
5665  *
5666  ********************************************************************/
5667
5668 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5669 {
5670         POLICY_HND *handle = &q_u->handle;
5671
5672         return _spoolss_enddocprinter_internal(p, handle);
5673 }
5674
5675 /****************************************************************************
5676 ****************************************************************************/
5677
5678 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5679 {
5680         POLICY_HND *handle = &q_u->handle;
5681         uint32 buffer_size = q_u->buffer_size;
5682         uint8 *buffer = q_u->buffer;
5683         uint32 *buffer_written = &q_u->buffer_size2;
5684         int snum;
5685         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5686         
5687         if (!Printer) {
5688                 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5689                 r_u->buffer_written = q_u->buffer_size2;
5690                 return WERR_BADFID;
5691         }
5692
5693         if (!get_printer_snum(p, handle, &snum))
5694                 return WERR_BADFID;
5695
5696         (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5697         if (*buffer_written == -1) {
5698                 r_u->buffer_written = 0;
5699                 if (errno == ENOSPC)
5700                         return WERR_NO_SPOOL_SPACE;
5701                 else
5702                         return WERR_ACCESS_DENIED;
5703         }
5704
5705         r_u->buffer_written = q_u->buffer_size2;
5706
5707         return WERR_OK;
5708 }
5709
5710 /********************************************************************
5711  * api_spoolss_getprinter
5712  * called from the spoolss dispatcher
5713  *
5714  ********************************************************************/
5715
5716 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5717                               pipes_struct *p)
5718 {
5719         struct current_user user;
5720         int snum;
5721         WERROR errcode = WERR_BADFUNC;
5722         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5723
5724         get_current_user(&user, p);
5725
5726         if (!Printer) {
5727                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5728                 return WERR_BADFID;
5729         }
5730
5731         if (!get_printer_snum(p, handle, &snum))
5732                 return WERR_BADFID;
5733
5734         switch (command) {
5735         case PRINTER_CONTROL_PAUSE:
5736                 if (print_queue_pause(&user, snum, &errcode)) {
5737                         errcode = WERR_OK;
5738                 }
5739                 break;
5740         case PRINTER_CONTROL_RESUME:
5741         case PRINTER_CONTROL_UNPAUSE:
5742                 if (print_queue_resume(&user, snum, &errcode)) {
5743                         errcode = WERR_OK;
5744                 }
5745                 break;
5746         case PRINTER_CONTROL_PURGE:
5747                 if (print_queue_purge(&user, snum, &errcode)) {
5748                         errcode = WERR_OK;
5749                 }
5750                 break;
5751         default:
5752                 return WERR_UNKNOWN_LEVEL;
5753         }
5754
5755         return errcode;
5756 }
5757
5758 /********************************************************************
5759  * api_spoolss_abortprinter
5760  * From MSDN: "Deletes printer's spool file if printer is configured
5761  * for spooling"
5762  ********************************************************************/
5763
5764 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5765 {
5766         POLICY_HND      *handle = &q_u->handle;
5767         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5768         int             snum;
5769         struct          current_user user;
5770         WERROR          errcode = WERR_OK;
5771         
5772         if (!Printer) {
5773                 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5774                 return WERR_BADFID;
5775         }
5776         
5777         if (!get_printer_snum(p, handle, &snum))
5778                 return WERR_BADFID;
5779         
5780         get_current_user( &user, p );   
5781         
5782         print_job_delete( &user, snum, Printer->jobid, &errcode );      
5783         
5784         return errcode;
5785 }
5786
5787 /********************************************************************
5788  * called by spoolss_api_setprinter
5789  * when updating a printer description
5790  ********************************************************************/
5791
5792 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5793                                  const SPOOL_PRINTER_INFO_LEVEL *info,
5794                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5795 {
5796         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5797         struct current_user user;
5798         WERROR result;
5799         int snum;
5800
5801         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5802
5803         if (!Printer || !get_printer_snum(p, handle, &snum)) {
5804                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5805                          OUR_HANDLE(handle)));
5806
5807                 result = WERR_BADFID;
5808                 goto done;
5809         }
5810
5811         /* NT seems to like setting the security descriptor even though
5812            nothing may have actually changed.  This causes annoying
5813            dialog boxes when the user doesn't have permission to change
5814            the security descriptor. */
5815
5816         nt_printing_getsec(p->mem_ctx, Printer->dev.handlename, &old_secdesc_ctr);
5817
5818         if (DEBUGLEVEL >= 10) {
5819                 SEC_ACL *the_acl;
5820                 int i;
5821
5822                 the_acl = old_secdesc_ctr->sec->dacl;
5823                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n", 
5824                            PRINTERNAME(snum), the_acl->num_aces));
5825
5826                 for (i = 0; i < the_acl->num_aces; i++) {
5827                         fstring sid_str;
5828
5829                         sid_to_string(sid_str, &the_acl->ace[i].trustee);
5830
5831                         DEBUG(10, ("%s 0x%08x\n", sid_str, 
5832                                   the_acl->ace[i].info.mask));
5833                 }
5834
5835                 the_acl = secdesc_ctr->sec->dacl;
5836
5837                 if (the_acl) {
5838                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n", 
5839                                    PRINTERNAME(snum), the_acl->num_aces));
5840
5841                         for (i = 0; i < the_acl->num_aces; i++) {
5842                                 fstring sid_str;
5843                                 
5844                                 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5845                                 
5846                                 DEBUG(10, ("%s 0x%08x\n", sid_str, 
5847                                            the_acl->ace[i].info.mask));
5848                         }
5849                 } else {
5850                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5851                 }
5852         }
5853
5854         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5855
5856         if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5857                 result = WERR_OK;
5858                 goto done;
5859         }
5860
5861         /* Work out which user is performing the operation */
5862
5863         get_current_user(&user, p);
5864
5865         /* Check the user has permissions to change the security
5866            descriptor.  By experimentation with two NT machines, the user
5867            requires Full Access to the printer to change security
5868            information. */
5869
5870         if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
5871                 result = WERR_ACCESS_DENIED;
5872                 goto done;
5873         }
5874
5875         result = nt_printing_setsec(Printer->dev.handlename, new_secdesc_ctr);
5876
5877  done:
5878
5879         return result;
5880 }
5881
5882 /********************************************************************
5883  Do Samba sanity checks on a printer info struct.
5884  this has changed purpose: it now "canonicalises" printer
5885  info from a client rather than just checking it is correct
5886  ********************************************************************/
5887
5888 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5889 {
5890         fstring printername;
5891         const char *p;
5892         
5893         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5894                  info->servername, info->printername, info->sharename, info->portname, info->drivername, info->comment, info->location));
5895
5896         /* we force some elements to "correct" values */
5897         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", get_called_name());
5898         fstrcpy(info->sharename, lp_servicename(snum));
5899         
5900         /* make sure printername is in \\server\printername format */
5901         
5902         fstrcpy( printername, info->printername );
5903         p = printername;
5904         if ( printername[0] == '\\' && printername[1] == '\\' ) {
5905                 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5906                         p++;
5907         }
5908         
5909         slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5910                  get_called_name(), p );
5911                  
5912         info->attributes = PRINTER_ATTRIBUTE_SAMBA;
5913         
5914         
5915         return True;
5916 }
5917
5918 /****************************************************************************
5919 ****************************************************************************/
5920
5921 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
5922 {
5923         extern userdom_struct current_user_info;
5924         char *cmd = lp_addprinter_cmd();
5925         char **qlines;
5926         pstring command;
5927         int numlines;
5928         int ret;
5929         int fd;
5930         fstring remote_machine = "%m";
5931
5932         standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5933         
5934         slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5935                         cmd, printer->info_2->printername, printer->info_2->sharename,
5936                         printer->info_2->portname, printer->info_2->drivername,
5937                         printer->info_2->location, printer->info_2->comment, remote_machine);
5938
5939         DEBUG(10,("Running [%s]\n", command));
5940         ret = smbrun(command, &fd);
5941         DEBUGADD(10,("returned [%d]\n", ret));
5942
5943         if ( ret != 0 ) {
5944                 if (fd != -1)
5945                         close(fd);
5946                 return False;
5947         }
5948
5949         numlines = 0;
5950         /* Get lines and convert them back to dos-codepage */
5951         qlines = fd_lines_load(fd, &numlines);
5952         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5953         close(fd);
5954
5955         if(numlines) {
5956                 /* Set the portname to what the script says the portname should be. */
5957                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5958                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5959
5960                 /* Send SIGHUP to process group... is there a better way? */
5961                 kill(0, SIGHUP);
5962                 
5963                 /* reload our services immediately */
5964                 reload_services( False );
5965         }
5966
5967         file_lines_free(qlines);
5968         return True;
5969 }
5970
5971 /********************************************************************
5972  * Called by spoolss_api_setprinter
5973  * when updating a printer description.
5974  ********************************************************************/
5975
5976 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
5977                            const SPOOL_PRINTER_INFO_LEVEL *info,
5978                            DEVICEMODE *devmode)
5979 {
5980         int snum;
5981         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5982         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5983         WERROR result;
5984         UNISTR2 buffer;
5985         fstring asc_buffer;
5986
5987         DEBUG(8,("update_printer\n"));
5988
5989         result = WERR_OK;
5990
5991         if (!Printer) {
5992                 result = WERR_BADFID;
5993                 goto done;
5994         }
5995
5996         if (!get_printer_snum(p, handle, &snum)) {
5997                 result = WERR_BADFID;
5998                 goto done;
5999         }
6000
6001         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6002             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6003                 result = WERR_BADFID;
6004                 goto done;
6005         }
6006
6007         DEBUGADD(8,("Converting info_2 struct\n"));
6008
6009         /*
6010          * convert_printer_info converts the incoming
6011          * info from the client and overwrites the info
6012          * just read from the tdb in the pointer 'printer'.
6013          */
6014
6015         if (!convert_printer_info(info, printer, level)) {
6016                 result =  WERR_NOMEM;
6017                 goto done;
6018         }
6019
6020         if (devmode) {
6021                 /* we have a valid devmode
6022                    convert it and link it*/
6023
6024                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6025                 if (!convert_devicemode(printer->info_2->printername, devmode,
6026                                 &printer->info_2->devmode)) {
6027                         result =  WERR_NOMEM;
6028                         goto done;
6029                 }
6030         }
6031
6032         /* Do sanity check on the requested changes for Samba */
6033
6034         if (!check_printer_ok(printer->info_2, snum)) {
6035                 result = WERR_INVALID_PARAM;
6036                 goto done;
6037         }
6038
6039         /* FIXME!!! If the driver has changed we really should verify that 
6040            it is installed before doing much else   --jerry */
6041
6042         /* Check calling user has permission to update printer description */
6043
6044         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6045                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6046                 result = WERR_ACCESS_DENIED;
6047                 goto done;
6048         }
6049
6050         /* Call addprinter hook */
6051         /* Check changes to see if this is really needed */
6052         
6053         if ( *lp_addprinter_cmd() 
6054                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6055                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6056                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6057                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6058         {
6059                 if ( !add_printer_hook(printer) ) {
6060                         result = WERR_ACCESS_DENIED;
6061                         goto done;
6062                 }
6063
6064                 /* 
6065                  * make sure we actually reload the services after 
6066                  * this as smb.conf could have a new section in it 
6067                  * .... shouldn't .... but could
6068                  */
6069                 reload_services(False); 
6070         }
6071         
6072         /*
6073          * When a *new* driver is bound to a printer, the drivername is used to
6074          * lookup previously saved driver initialization info, which is then
6075          * bound to the printer, simulating what happens in the Windows arch.
6076          */
6077         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6078         {
6079                 if (!set_driver_init(printer, 2)) 
6080                 {
6081                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6082                                 printer->info_2->drivername));
6083                 }
6084                 
6085                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6086                         printer->info_2->drivername));
6087                         
6088                 notify_printer_driver(snum, printer->info_2->drivername);
6089         }
6090
6091         /* 
6092          * flag which changes actually occured.  This is a small subset of 
6093          * all the possible changes.  We also have to update things in the 
6094          * DsSpooler key.
6095          */
6096
6097         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6098                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6099                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6100                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6101
6102                 notify_printer_comment(snum, printer->info_2->comment);
6103         }
6104
6105         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6106                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6107                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6108                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6109
6110                 notify_printer_sharename(snum, printer->info_2->sharename);
6111         }
6112
6113         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6114                 char *pname;
6115                 
6116                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6117                         pname++;
6118                 else
6119                         pname = printer->info_2->printername;
6120                         
6121
6122                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6123                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6124                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6125
6126                 notify_printer_printername( snum, pname );
6127         }
6128         
6129         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6130                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6131                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6132                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6133
6134                 notify_printer_port(snum, printer->info_2->portname);
6135         }
6136
6137         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6138                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6139                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6140                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6141
6142                 notify_printer_location(snum, printer->info_2->location);
6143         }
6144         
6145         /* here we need to update some more DsSpooler keys */
6146         /* uNCName, serverName, shortServerName */
6147         
6148         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6149         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6150                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6151         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6152                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6153
6154         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6155                  global_myname(), printer->info_2->sharename );
6156         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6157         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6158                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6159
6160         /* Update printer info */
6161         result = mod_a_printer(*printer, 2);
6162
6163 done:
6164         free_a_printer(&printer, 2);
6165         free_a_printer(&old_printer, 2);
6166
6167
6168         return result;
6169 }
6170
6171 /****************************************************************************
6172 ****************************************************************************/
6173 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6174                                    const SPOOL_PRINTER_INFO_LEVEL *info)
6175 {
6176 #ifdef HAVE_ADS
6177         SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6178         int snum;
6179         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6180
6181         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6182
6183         if (!Printer)
6184                 return WERR_BADFID;
6185
6186         if (!get_printer_snum(p, handle, &snum))
6187                 return WERR_BADFID;
6188         
6189         nt_printer_publish(Printer, snum, info7->action);
6190         
6191         return WERR_OK;
6192 #else
6193         return WERR_UNKNOWN_LEVEL;
6194 #endif
6195 }
6196 /****************************************************************************
6197 ****************************************************************************/
6198
6199 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6200 {
6201         POLICY_HND *handle = &q_u->handle;
6202         uint32 level = q_u->level;
6203         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6204         DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6205         SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6206         uint32 command = q_u->command;
6207
6208         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6209         
6210         if (!Printer) {
6211                 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6212                 return WERR_BADFID;
6213         }
6214
6215         /* check the level */   
6216         switch (level) {
6217                 case 0:
6218                         return control_printer(handle, command, p);
6219                 case 2:
6220                         return update_printer(p, handle, level, info, devmode_ctr.devmode);
6221                 case 3:
6222                         return update_printer_sec(handle, level, info, p,
6223                                                   secdesc_ctr);
6224                 case 7:
6225                         return publish_or_unpublish_printer(p, handle, info);
6226                 default:
6227                         return WERR_UNKNOWN_LEVEL;
6228         }
6229 }
6230
6231 /****************************************************************************
6232 ****************************************************************************/
6233
6234 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6235 {
6236         POLICY_HND *handle = &q_u->handle;
6237         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6238         
6239         if (!Printer) {
6240                 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6241                 return WERR_BADFID;
6242         }
6243
6244         if (Printer->notify.client_connected==True) {
6245                 int snum = -1;
6246
6247                 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6248                         snum = -1;
6249                 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6250                                 !get_printer_snum(p, handle, &snum) )
6251                         return WERR_BADFID;
6252
6253                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6254         }
6255
6256         Printer->notify.flags=0;
6257         Printer->notify.options=0;
6258         Printer->notify.localmachine[0]='\0';
6259         Printer->notify.printerlocal=0;
6260         if (Printer->notify.option)
6261                 free_spool_notify_option(&Printer->notify.option);
6262         Printer->notify.client_connected=False;
6263
6264         return WERR_OK;
6265 }
6266
6267 /****************************************************************************
6268 ****************************************************************************/
6269
6270 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6271 {
6272         /* that's an [in out] buffer (despite appearences to the contrary) */
6273         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6274
6275         r_u->needed = 0;
6276         return WERR_INVALID_PARAM; /* this is what a NT server
6277                                            returns for AddJob. AddJob
6278                                            must fail on non-local
6279                                            printers */
6280 }
6281
6282 /****************************************************************************
6283 ****************************************************************************/
6284
6285 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6286                             int position, int snum)
6287 {
6288         pstring temp_name;
6289         
6290         struct tm *t;
6291         
6292         t=gmtime(&queue->time);
6293         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6294
6295         job_info->jobid=queue->job;     
6296         init_unistr(&job_info->printername, lp_servicename(snum));
6297         init_unistr(&job_info->machinename, temp_name);
6298         init_unistr(&job_info->username, queue->fs_user);
6299         init_unistr(&job_info->document, queue->fs_file);
6300         init_unistr(&job_info->datatype, "RAW");
6301         init_unistr(&job_info->text_status, "");
6302         job_info->status=nt_printj_status(queue->status);
6303         job_info->priority=queue->priority;
6304         job_info->position=position;
6305         job_info->totalpages=queue->page_count;
6306         job_info->pagesprinted=0;
6307
6308         make_systemtime(&job_info->submitted, t);
6309 }
6310
6311 /****************************************************************************
6312 ****************************************************************************/
6313
6314 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6315                             int position, int snum, 
6316                             NT_PRINTER_INFO_LEVEL *ntprinter,
6317                             DEVICEMODE *devmode)
6318 {
6319         pstring temp_name;
6320         struct tm *t;
6321
6322         t=gmtime(&queue->time);
6323         slprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", get_called_name());
6324
6325         job_info->jobid=queue->job;
6326         
6327         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6328         
6329         init_unistr(&job_info->machinename, temp_name);
6330         init_unistr(&job_info->username, queue->fs_user);
6331         init_unistr(&job_info->document, queue->fs_file);
6332         init_unistr(&job_info->notifyname, queue->fs_user);
6333         init_unistr(&job_info->datatype, "RAW");
6334         init_unistr(&job_info->printprocessor, "winprint");
6335         init_unistr(&job_info->parameters, "");
6336         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6337         init_unistr(&job_info->text_status, "");
6338         
6339 /* and here the security descriptor */
6340
6341         job_info->status=nt_printj_status(queue->status);
6342         job_info->priority=queue->priority;
6343         job_info->position=position;
6344         job_info->starttime=0;
6345         job_info->untiltime=0;
6346         job_info->totalpages=queue->page_count;
6347         job_info->size=queue->size;
6348         make_systemtime(&(job_info->submitted), t);
6349         job_info->timeelapsed=0;
6350         job_info->pagesprinted=0;
6351
6352         job_info->devmode = devmode;
6353
6354         return (True);
6355 }
6356
6357 /****************************************************************************
6358  Enumjobs at level 1.
6359 ****************************************************************************/
6360
6361 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6362                               NEW_BUFFER *buffer, uint32 offered,
6363                               uint32 *needed, uint32 *returned)
6364 {
6365         JOB_INFO_1 *info;
6366         int i;
6367         
6368         info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
6369         if (info==NULL) {
6370                 SAFE_FREE(queue);
6371                 *returned=0;
6372                 return WERR_NOMEM;
6373         }
6374         
6375         for (i=0; i<*returned; i++)
6376                 fill_job_info_1(&info[i], &queue[i], i, snum);
6377
6378         SAFE_FREE(queue);
6379
6380         /* check the required size. */  
6381         for (i=0; i<*returned; i++)
6382                 (*needed) += spoolss_size_job_info_1(&info[i]);
6383
6384         if (!alloc_buffer_size(buffer, *needed)) {
6385                 SAFE_FREE(info);
6386                 return WERR_INSUFFICIENT_BUFFER;
6387         }
6388
6389         /* fill the buffer with the structures */
6390         for (i=0; i<*returned; i++)
6391                 smb_io_job_info_1("", buffer, &info[i], 0);     
6392
6393         /* clear memory */
6394         SAFE_FREE(info);
6395
6396         if (*needed > offered) {
6397                 *returned=0;
6398                 return WERR_INSUFFICIENT_BUFFER;
6399         }
6400
6401         return WERR_OK;
6402 }
6403
6404 /****************************************************************************
6405  Enumjobs at level 2.
6406 ****************************************************************************/
6407
6408 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6409                               NEW_BUFFER *buffer, uint32 offered,
6410                               uint32 *needed, uint32 *returned)
6411 {
6412         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6413         JOB_INFO_2 *info = NULL;
6414         int i;
6415         WERROR result;
6416         DEVICEMODE *devmode = NULL;
6417         
6418         info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
6419         if (info==NULL) {
6420                 *returned=0;
6421                 result = WERR_NOMEM;
6422                 goto done;
6423         }
6424
6425         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6426         if (!W_ERROR_IS_OK(result)) {
6427                 *returned = 0;
6428                 goto done;
6429         }
6430                 
6431         /* this should not be a failure condition if the devmode is NULL */
6432         
6433         devmode = construct_dev_mode(snum);
6434
6435         for (i=0; i<*returned; i++)
6436                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
6437                                 devmode);
6438
6439         free_a_printer(&ntprinter, 2);
6440         SAFE_FREE(queue);
6441
6442         /* check the required size. */  
6443         for (i=0; i<*returned; i++)
6444                 (*needed) += spoolss_size_job_info_2(&info[i]);
6445
6446         if (*needed > offered) {
6447                 *returned=0;
6448                 result = WERR_INSUFFICIENT_BUFFER;
6449                 goto done;
6450         }
6451
6452         if (!alloc_buffer_size(buffer, *needed)) {
6453                 SAFE_FREE(info);
6454                 result = WERR_INSUFFICIENT_BUFFER;
6455                 goto done;
6456         }
6457
6458         /* fill the buffer with the structures */
6459         for (i=0; i<*returned; i++)
6460                 smb_io_job_info_2("", buffer, &info[i], 0);     
6461
6462         result = WERR_OK;
6463
6464  done:
6465         free_a_printer(&ntprinter, 2);
6466         free_devmode(devmode);
6467         SAFE_FREE(queue);
6468         SAFE_FREE(info);
6469
6470         return result;
6471
6472 }
6473
6474 /****************************************************************************
6475  Enumjobs.
6476 ****************************************************************************/
6477
6478 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6479 {       
6480         POLICY_HND *handle = &q_u->handle;
6481         uint32 level = q_u->level;
6482         NEW_BUFFER *buffer = NULL;
6483         uint32 offered = q_u->offered;
6484         uint32 *needed = &r_u->needed;
6485         uint32 *returned = &r_u->returned;
6486         WERROR wret;
6487
6488         int snum;
6489         print_status_struct prt_status;
6490         print_queue_struct *queue=NULL;
6491
6492         /* that's an [in out] buffer */
6493         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6494         buffer = r_u->buffer;
6495
6496         DEBUG(4,("_spoolss_enumjobs\n"));
6497
6498         *needed=0;
6499         *returned=0;
6500
6501         if (!get_printer_snum(p, handle, &snum))
6502                 return WERR_BADFID;
6503
6504         *returned = print_queue_status(snum, &queue, &prt_status);
6505         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6506
6507         if (*returned == 0) {
6508                 SAFE_FREE(queue);
6509                 return WERR_OK;
6510         }
6511
6512         switch (level) {
6513         case 1:
6514                 wret = enumjobs_level1(queue, snum, buffer, offered, needed, returned);
6515                 return wret;
6516         case 2:
6517                 wret = enumjobs_level2(queue, snum, buffer, offered, needed, returned);
6518                 return wret;
6519         default:
6520                 SAFE_FREE(queue);
6521                 *returned=0;
6522                 return WERR_UNKNOWN_LEVEL;
6523         }
6524 }
6525
6526 /****************************************************************************
6527 ****************************************************************************/
6528
6529 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6530 {
6531         return WERR_OK;
6532 }
6533
6534 /****************************************************************************
6535 ****************************************************************************/
6536
6537 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6538 {
6539         POLICY_HND *handle = &q_u->handle;
6540         uint32 jobid = q_u->jobid;
6541         uint32 command = q_u->command;
6542
6543         struct current_user user;
6544         int snum;
6545         WERROR errcode = WERR_BADFUNC;
6546                 
6547         if (!get_printer_snum(p, handle, &snum)) {
6548                 return WERR_BADFID;
6549         }
6550
6551         if (!print_job_exists(snum, jobid)) {
6552                 return WERR_INVALID_PRINTER_NAME;
6553         }
6554
6555         get_current_user(&user, p);     
6556
6557         switch (command) {
6558         case JOB_CONTROL_CANCEL:
6559         case JOB_CONTROL_DELETE:
6560                 if (print_job_delete(&user, snum, jobid, &errcode)) {
6561                         errcode = WERR_OK;
6562                 }
6563                 break;
6564         case JOB_CONTROL_PAUSE:
6565                 if (print_job_pause(&user, snum, jobid, &errcode)) {
6566                         errcode = WERR_OK;
6567                 }               
6568                 break;
6569         case JOB_CONTROL_RESTART:
6570         case JOB_CONTROL_RESUME:
6571                 if (print_job_resume(&user, snum, jobid, &errcode)) {
6572                         errcode = WERR_OK;
6573                 }
6574                 break;
6575         default:
6576                 return WERR_UNKNOWN_LEVEL;
6577         }
6578
6579         return errcode;
6580 }
6581
6582 /****************************************************************************
6583  Enumerates all printer drivers at level 1.
6584 ****************************************************************************/
6585
6586 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6587 {
6588         int i;
6589         int ndrivers;
6590         uint32 version;
6591         fstring *list = NULL;
6592
6593         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6594         DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6595
6596         *returned=0;
6597
6598         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6599                 list=NULL;
6600                 ndrivers=get_ntdrivers(&list, architecture, version);
6601                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6602
6603                 if(ndrivers == -1)
6604                         return WERR_NOMEM;
6605
6606                 if(ndrivers != 0) {
6607                         if((tdi1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
6608                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6609                                 SAFE_FREE(driver_info_1);
6610                                 SAFE_FREE(list);
6611                                 return WERR_NOMEM;
6612                         }
6613                         else driver_info_1 = tdi1;
6614                 }
6615
6616                 for (i=0; i<ndrivers; i++) {
6617                         WERROR status;
6618                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6619                         ZERO_STRUCT(driver);
6620                         status = get_a_printer_driver(&driver, 3, list[i], 
6621                                                       architecture, version);
6622                         if (!W_ERROR_IS_OK(status)) {
6623                                 SAFE_FREE(list);
6624                                 return status;
6625                         }
6626                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );             
6627                         free_a_printer_driver(driver, 3);
6628                 }       
6629
6630                 *returned+=ndrivers;
6631                 SAFE_FREE(list);
6632         }
6633         
6634         /* check the required size. */
6635         for (i=0; i<*returned; i++) {
6636                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6637                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6638         }
6639
6640         if (!alloc_buffer_size(buffer, *needed)) {
6641                 SAFE_FREE(driver_info_1);
6642                 return WERR_INSUFFICIENT_BUFFER;
6643         }
6644
6645         /* fill the buffer with the driver structures */
6646         for (i=0; i<*returned; i++) {
6647                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6648                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6649         }
6650
6651         SAFE_FREE(driver_info_1);
6652
6653         if (*needed > offered) {
6654                 *returned=0;
6655                 return WERR_INSUFFICIENT_BUFFER;
6656         }
6657
6658         return WERR_OK;
6659 }
6660
6661 /****************************************************************************
6662  Enumerates all printer drivers at level 2.
6663 ****************************************************************************/
6664
6665 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6666 {
6667         int i;
6668         int ndrivers;
6669         uint32 version;
6670         fstring *list = NULL;
6671
6672         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6673         DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6674
6675         *returned=0;
6676
6677         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6678                 list=NULL;
6679                 ndrivers=get_ntdrivers(&list, architecture, version);
6680                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6681
6682                 if(ndrivers == -1)
6683                         return WERR_NOMEM;
6684
6685                 if(ndrivers != 0) {
6686                         if((tdi2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
6687                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6688                                 SAFE_FREE(driver_info_2);
6689                                 SAFE_FREE(list);
6690                                 return WERR_NOMEM;
6691                         }
6692                         else driver_info_2 = tdi2;
6693                 }
6694                 
6695                 for (i=0; i<ndrivers; i++) {
6696                         WERROR status;
6697
6698                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6699                         ZERO_STRUCT(driver);
6700                         status = get_a_printer_driver(&driver, 3, list[i], 
6701                                                       architecture, version);
6702                         if (!W_ERROR_IS_OK(status)) {
6703                                 SAFE_FREE(list);
6704                                 return status;
6705                         }
6706                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);            
6707                         free_a_printer_driver(driver, 3);
6708                 }       
6709
6710                 *returned+=ndrivers;
6711                 SAFE_FREE(list);
6712         }
6713         
6714         /* check the required size. */
6715         for (i=0; i<*returned; i++) {
6716                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6717                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6718         }
6719
6720         if (!alloc_buffer_size(buffer, *needed)) {
6721                 SAFE_FREE(driver_info_2);
6722                 return WERR_INSUFFICIENT_BUFFER;
6723         }
6724
6725         /* fill the buffer with the form structures */
6726         for (i=0; i<*returned; i++) {
6727                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6728                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6729         }
6730
6731         SAFE_FREE(driver_info_2);
6732
6733         if (*needed > offered) {
6734                 *returned=0;
6735                 return WERR_INSUFFICIENT_BUFFER;
6736         }
6737
6738         return WERR_OK;
6739 }
6740
6741 /****************************************************************************
6742  Enumerates all printer drivers at level 3.
6743 ****************************************************************************/
6744
6745 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6746 {
6747         int i;
6748         int ndrivers;
6749         uint32 version;
6750         fstring *list = NULL;
6751
6752         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6753         DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6754
6755         *returned=0;
6756
6757         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6758                 list=NULL;
6759                 ndrivers=get_ntdrivers(&list, architecture, version);
6760                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6761
6762                 if(ndrivers == -1)
6763                         return WERR_NOMEM;
6764
6765                 if(ndrivers != 0) {
6766                         if((tdi3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
6767                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6768                                 SAFE_FREE(driver_info_3);
6769                                 SAFE_FREE(list);
6770                                 return WERR_NOMEM;
6771                         }
6772                         else driver_info_3 = tdi3;
6773                 }
6774
6775                 for (i=0; i<ndrivers; i++) {
6776                         WERROR status;
6777
6778                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6779                         ZERO_STRUCT(driver);
6780                         status = get_a_printer_driver(&driver, 3, list[i], 
6781                                                       architecture, version);
6782                         if (!W_ERROR_IS_OK(status)) {
6783                                 SAFE_FREE(list);
6784                                 return status;
6785                         }
6786                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);            
6787                         free_a_printer_driver(driver, 3);
6788                 }       
6789
6790                 *returned+=ndrivers;
6791                 SAFE_FREE(list);
6792         }
6793
6794         /* check the required size. */
6795         for (i=0; i<*returned; i++) {
6796                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6797                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6798         }
6799
6800         if (!alloc_buffer_size(buffer, *needed)) {
6801                 SAFE_FREE(driver_info_3);
6802                 return WERR_INSUFFICIENT_BUFFER;
6803         }
6804         
6805         /* fill the buffer with the driver structures */
6806         for (i=0; i<*returned; i++) {
6807                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6808                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6809         }
6810
6811         for (i=0; i<*returned; i++)
6812                 SAFE_FREE(driver_info_3[i].dependentfiles);
6813         
6814         SAFE_FREE(driver_info_3);
6815         
6816         if (*needed > offered) {
6817                 *returned=0;
6818                 return WERR_INSUFFICIENT_BUFFER;
6819         }
6820
6821         return WERR_OK;
6822 }
6823
6824 /****************************************************************************
6825  Enumerates all printer drivers.
6826 ****************************************************************************/
6827
6828 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6829 {
6830         UNISTR2 *environment = &q_u->environment;
6831         uint32 level = q_u->level;
6832         NEW_BUFFER *buffer = NULL;
6833         uint32 offered = q_u->offered;
6834         uint32 *needed = &r_u->needed;
6835         uint32 *returned = &r_u->returned;
6836
6837         fstring *list = NULL;
6838         fstring servername;
6839         fstring architecture;
6840
6841         /* that's an [in out] buffer */
6842         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6843         buffer = r_u->buffer;
6844
6845         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6846         fstrcpy(servername, get_called_name());
6847         *needed=0;
6848         *returned=0;
6849
6850         unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
6851
6852         switch (level) {
6853         case 1:
6854                 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6855         case 2:
6856                 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6857         case 3:
6858                 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6859         default:
6860                 *returned=0;
6861                 SAFE_FREE(list);
6862                 return WERR_UNKNOWN_LEVEL;
6863         }
6864 }
6865
6866 /****************************************************************************
6867 ****************************************************************************/
6868
6869 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6870 {
6871         form->flag=list->flag;
6872         init_unistr(&form->name, list->name);
6873         form->width=list->width;
6874         form->length=list->length;
6875         form->left=list->left;
6876         form->top=list->top;
6877         form->right=list->right;
6878         form->bottom=list->bottom;      
6879 }
6880         
6881 /****************************************************************************
6882 ****************************************************************************/
6883
6884 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6885 {
6886         uint32 level = q_u->level;
6887         NEW_BUFFER *buffer = NULL;
6888         uint32 offered = q_u->offered;
6889         uint32 *needed = &r_u->needed;
6890         uint32 *numofforms = &r_u->numofforms;
6891         uint32 numbuiltinforms;
6892
6893         nt_forms_struct *list=NULL;
6894         nt_forms_struct *builtinlist=NULL;
6895         FORM_1 *forms_1;
6896         int buffer_size=0;
6897         int i;
6898
6899         /* that's an [in out] buffer */
6900         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
6901         buffer = r_u->buffer;
6902
6903         DEBUG(4,("_spoolss_enumforms\n"));
6904         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6905         DEBUGADD(5,("Info level [%d]\n",          level));
6906
6907         numbuiltinforms = get_builtin_ntforms(&builtinlist);
6908         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
6909         *numofforms = get_ntforms(&list);
6910         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
6911         *numofforms += numbuiltinforms;
6912
6913         if (*numofforms == 0) return WERR_NO_MORE_ITEMS;
6914
6915         switch (level) {
6916         case 1:
6917                 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
6918                         *numofforms=0;
6919                         return WERR_NOMEM;
6920                 }
6921
6922                 /* construct the list of form structures */
6923                 for (i=0; i<numbuiltinforms; i++) {
6924                         DEBUGADD(6,("Filling form number [%d]\n",i));
6925                         fill_form_1(&forms_1[i], &builtinlist[i]);
6926                 }
6927                 
6928                 SAFE_FREE(builtinlist);
6929
6930                 for (; i<*numofforms; i++) {
6931                         DEBUGADD(6,("Filling form number [%d]\n",i));
6932                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
6933                 }
6934                 
6935                 SAFE_FREE(list);
6936
6937                 /* check the required size. */
6938                 for (i=0; i<numbuiltinforms; i++) {
6939                         DEBUGADD(6,("adding form [%d]'s size\n",i));
6940                         buffer_size += spoolss_size_form_1(&forms_1[i]);
6941                 }
6942                 for (; i<*numofforms; i++) {
6943                         DEBUGADD(6,("adding form [%d]'s size\n",i));
6944                         buffer_size += spoolss_size_form_1(&forms_1[i]);
6945                 }
6946
6947                 *needed=buffer_size;            
6948                 
6949                 if (!alloc_buffer_size(buffer, buffer_size)){
6950                         SAFE_FREE(forms_1);
6951                         return WERR_INSUFFICIENT_BUFFER;
6952                 }
6953
6954                 /* fill the buffer with the form structures */
6955                 for (i=0; i<numbuiltinforms; i++) {
6956                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
6957                         smb_io_form_1("", buffer, &forms_1[i], 0);
6958                 }
6959                 for (; i<*numofforms; i++) {
6960                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
6961                         smb_io_form_1("", buffer, &forms_1[i], 0);
6962                 }
6963
6964                 SAFE_FREE(forms_1);
6965
6966                 if (*needed > offered) {
6967                         *numofforms=0;
6968                         return WERR_INSUFFICIENT_BUFFER;
6969                 }
6970                 else
6971                         return WERR_OK;
6972                         
6973         default:
6974                 SAFE_FREE(list);
6975                 SAFE_FREE(builtinlist);
6976                 return WERR_UNKNOWN_LEVEL;
6977         }
6978
6979 }
6980
6981 /****************************************************************************
6982 ****************************************************************************/
6983
6984 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
6985 {
6986         uint32 level = q_u->level;
6987         UNISTR2 *uni_formname = &q_u->formname;
6988         NEW_BUFFER *buffer = NULL;
6989         uint32 offered = q_u->offered;
6990         uint32 *needed = &r_u->needed;
6991
6992         nt_forms_struct *list=NULL;
6993         nt_forms_struct builtin_form;
6994         BOOL foundBuiltin;
6995         FORM_1 form_1;
6996         fstring form_name;
6997         int buffer_size=0;
6998         int numofforms=0, i=0;
6999
7000         /* that's an [in out] buffer */
7001         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7002         buffer = r_u->buffer;
7003
7004         unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7005
7006         DEBUG(4,("_spoolss_getform\n"));
7007         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7008         DEBUGADD(5,("Info level [%d]\n",          level));
7009
7010         foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7011         if (!foundBuiltin) {
7012                 numofforms = get_ntforms(&list);
7013                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7014
7015                 if (numofforms == 0)
7016                         return WERR_BADFID;
7017         }
7018
7019         switch (level) {
7020         case 1:
7021                 if (foundBuiltin) {
7022                         fill_form_1(&form_1, &builtin_form);
7023                 } else {
7024
7025                         /* Check if the requested name is in the list of form structures */
7026                         for (i=0; i<numofforms; i++) {
7027
7028                                 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7029
7030                                 if (strequal(form_name, list[i].name)) {
7031                                         DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7032                                         fill_form_1(&form_1, &list[i]);
7033                                         break;
7034                                 }
7035                         }
7036                         
7037                         SAFE_FREE(list);
7038                         if (i == numofforms) {
7039                                 return WERR_BADFID;
7040                         }
7041                 }
7042                 /* check the required size. */
7043
7044                 *needed=spoolss_size_form_1(&form_1);
7045                 
7046                 if (!alloc_buffer_size(buffer, buffer_size)){
7047                         return WERR_INSUFFICIENT_BUFFER;
7048                 }
7049
7050                 if (*needed > offered) {
7051                         return WERR_INSUFFICIENT_BUFFER;
7052                 }
7053
7054                 /* fill the buffer with the form structures */
7055                 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7056                 smb_io_form_1("", buffer, &form_1, 0);
7057
7058                 return WERR_OK;
7059                         
7060         default:
7061                 SAFE_FREE(list);
7062                 return WERR_UNKNOWN_LEVEL;
7063         }
7064 }
7065
7066 /****************************************************************************
7067 ****************************************************************************/
7068
7069 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7070 {
7071         init_unistr(&port->port_name, name);
7072 }
7073
7074 /****************************************************************************
7075 ****************************************************************************/
7076
7077 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7078 {
7079         init_unistr(&port->port_name, name);
7080         init_unistr(&port->monitor_name, "Local Monitor");
7081         init_unistr(&port->description, "Local Port");
7082         port->port_type=PORT_TYPE_WRITE;
7083         port->reserved=0x0;     
7084 }
7085
7086 /****************************************************************************
7087  enumports level 1.
7088 ****************************************************************************/
7089
7090 static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7091 {
7092         PORT_INFO_1 *ports=NULL;
7093         int i=0;
7094
7095         if (*lp_enumports_cmd()) {
7096                 char *cmd = lp_enumports_cmd();
7097                 char **qlines;
7098                 pstring command;
7099                 int numlines;
7100                 int ret;
7101                 int fd;
7102
7103                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7104
7105                 DEBUG(10,("Running [%s]\n", command));
7106                 ret = smbrun(command, &fd);
7107                 DEBUG(10,("Returned [%d]\n", ret));
7108                 if (ret != 0) {
7109                         if (fd != -1)
7110                                 close(fd);
7111                         /* Is this the best error to return here? */
7112                         return WERR_ACCESS_DENIED;
7113                 }
7114
7115                 numlines = 0;
7116                 qlines = fd_lines_load(fd, &numlines);
7117                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7118                 close(fd);
7119
7120                 if(numlines) {
7121                         if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
7122                                 DEBUG(10,("Returning WERR_NOMEM [%s]\n", 
7123                                           dos_errstr(WERR_NOMEM)));
7124                                 file_lines_free(qlines);
7125                                 return WERR_NOMEM;
7126                         }
7127
7128                         for (i=0; i<numlines; i++) {
7129                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7130                                 fill_port_1(&ports[i], qlines[i]);
7131                         }
7132
7133                         file_lines_free(qlines);
7134                 }
7135
7136                 *returned = numlines;
7137
7138         } else {
7139                 *returned = 1; /* Sole Samba port returned. */
7140
7141                 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
7142                         return WERR_NOMEM;
7143         
7144                 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7145
7146                 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7147         }
7148
7149         /* check the required size. */
7150         for (i=0; i<*returned; i++) {
7151                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7152                 *needed += spoolss_size_port_info_1(&ports[i]);
7153         }
7154                 
7155         if (!alloc_buffer_size(buffer, *needed)) {
7156                 SAFE_FREE(ports);
7157                 return WERR_INSUFFICIENT_BUFFER;
7158         }
7159
7160         /* fill the buffer with the ports structures */
7161         for (i=0; i<*returned; i++) {
7162                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7163                 smb_io_port_1("", buffer, &ports[i], 0);
7164         }
7165
7166         SAFE_FREE(ports);
7167
7168         if (*needed > offered) {
7169                 *returned=0;
7170                 return WERR_INSUFFICIENT_BUFFER;
7171         }
7172
7173         return WERR_OK;
7174 }
7175
7176 /****************************************************************************
7177  enumports level 2.
7178 ****************************************************************************/
7179
7180 static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7181 {
7182         PORT_INFO_2 *ports=NULL;
7183         int i=0;
7184
7185         if (*lp_enumports_cmd()) {
7186                 char *cmd = lp_enumports_cmd();
7187                 char *path;
7188                 char **qlines;
7189                 pstring tmp_file;
7190                 pstring command;
7191                 int numlines;
7192                 int ret;
7193                 int fd;
7194
7195                 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7196                         path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7197                 else
7198                         path = lp_lockdir();
7199
7200                 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7201                 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7202
7203                 unlink(tmp_file);
7204                 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7205                 ret = smbrun(command, &fd);
7206                 DEBUGADD(10,("returned [%d]\n", ret));
7207                 if (ret != 0) {
7208                         if (fd != -1)
7209                                 close(fd);
7210                         /* Is this the best error to return here? */
7211                         return WERR_ACCESS_DENIED;
7212                 }
7213
7214                 numlines = 0;
7215                 qlines = fd_lines_load(fd, &numlines);
7216                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7217                 close(fd);
7218
7219                 if(numlines) {
7220                         if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
7221                                 file_lines_free(qlines);
7222                                 return WERR_NOMEM;
7223                         }
7224
7225                         for (i=0; i<numlines; i++) {
7226                                 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7227                                 fill_port_2(&(ports[i]), qlines[i]);
7228                         }
7229
7230                         file_lines_free(qlines);
7231                 }
7232
7233                 *returned = numlines;
7234
7235         } else {
7236
7237                 *returned = 1;
7238
7239                 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
7240                         return WERR_NOMEM;
7241         
7242                 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7243
7244                 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7245         }
7246
7247         /* check the required size. */
7248         for (i=0; i<*returned; i++) {
7249                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7250                 *needed += spoolss_size_port_info_2(&ports[i]);
7251         }
7252                 
7253         if (!alloc_buffer_size(buffer, *needed)) {
7254                 SAFE_FREE(ports);
7255                 return WERR_INSUFFICIENT_BUFFER;
7256         }
7257
7258         /* fill the buffer with the ports structures */
7259         for (i=0; i<*returned; i++) {
7260                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7261                 smb_io_port_2("", buffer, &ports[i], 0);
7262         }
7263
7264         SAFE_FREE(ports);
7265
7266         if (*needed > offered) {
7267                 *returned=0;
7268                 return WERR_INSUFFICIENT_BUFFER;
7269         }
7270
7271         return WERR_OK;
7272 }
7273
7274 /****************************************************************************
7275  enumports.
7276 ****************************************************************************/
7277
7278 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7279 {
7280         uint32 level = q_u->level;
7281         NEW_BUFFER *buffer = NULL;
7282         uint32 offered = q_u->offered;
7283         uint32 *needed = &r_u->needed;
7284         uint32 *returned = &r_u->returned;
7285
7286         /* that's an [in out] buffer */
7287         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7288         buffer = r_u->buffer;
7289
7290         DEBUG(4,("_spoolss_enumports\n"));
7291         
7292         *returned=0;
7293         *needed=0;
7294         
7295         switch (level) {
7296         case 1:
7297                 return enumports_level_1(buffer, offered, needed, returned);
7298         case 2:
7299                 return enumports_level_2(buffer, offered, needed, returned);
7300         default:
7301                 return WERR_UNKNOWN_LEVEL;
7302         }
7303 }
7304
7305 /****************************************************************************
7306 ****************************************************************************/
7307
7308 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7309                                 const SPOOL_PRINTER_INFO_LEVEL *info,
7310                                 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7311                                 uint32 user_switch, const SPOOL_USER_CTR *user,
7312                                 POLICY_HND *handle)
7313 {
7314         NT_PRINTER_INFO_LEVEL *printer = NULL;
7315         fstring name;
7316         int     snum;
7317         WERROR err = WERR_OK;
7318
7319         if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
7320                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7321                 return WERR_NOMEM;
7322         }
7323
7324         ZERO_STRUCTP(printer);
7325
7326         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7327         if (!convert_printer_info(info, printer, 2)) {
7328                 free_a_printer(&printer, 2);
7329                 return WERR_NOMEM;
7330         }
7331
7332         /* check to see if the printer already exists */
7333
7334         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7335                 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n", 
7336                         printer->info_2->sharename));
7337                 free_a_printer(&printer, 2);
7338                 return WERR_PRINTER_ALREADY_EXISTS;
7339         }
7340         
7341         /* FIXME!!!  smbd should check to see if the driver is installed before
7342            trying to add a printer like this  --jerry */
7343
7344         if (*lp_addprinter_cmd() ) {
7345                 if ( !add_printer_hook(printer) ) {
7346                         free_a_printer(&printer,2);
7347                         return WERR_ACCESS_DENIED;
7348         }
7349         }
7350
7351         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
7352              printer->info_2->sharename);
7353
7354         
7355         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7356                 free_a_printer(&printer,2);
7357                 return WERR_ACCESS_DENIED;
7358         }
7359
7360         /* you must be a printer admin to add a new printer */
7361         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7362                 free_a_printer(&printer,2);
7363                 return WERR_ACCESS_DENIED;              
7364         }
7365         
7366         /*
7367          * Do sanity check on the requested changes for Samba.
7368          */
7369
7370         if (!check_printer_ok(printer->info_2, snum)) {
7371                 free_a_printer(&printer,2);
7372                 return WERR_INVALID_PARAM;
7373         }
7374
7375         /*
7376          * When a printer is created, the drivername bound to the printer is used
7377          * to lookup previously saved driver initialization info, which is then 
7378          * bound to the new printer, simulating what happens in the Windows arch.
7379          */
7380
7381         if (!devmode)
7382         {
7383                 set_driver_init(printer, 2);
7384         }
7385         else 
7386         {
7387                 /* A valid devmode was included, convert and link it
7388                 */
7389                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7390
7391                 if (!convert_devicemode(printer->info_2->printername, devmode,
7392                                 &printer->info_2->devmode))
7393                         return  WERR_NOMEM;
7394         }
7395
7396         /* write the ASCII on disk */
7397         err = mod_a_printer(*printer, 2);
7398         if (!W_ERROR_IS_OK(err)) {
7399                 free_a_printer(&printer,2);
7400                 return err;
7401         }
7402
7403         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7404                 /* Handle open failed - remove addition. */
7405                 del_a_printer(printer->info_2->sharename);
7406                 free_a_printer(&printer,2);
7407                 return WERR_ACCESS_DENIED;
7408         }
7409
7410         update_c_setprinter(False);
7411         free_a_printer(&printer,2);
7412
7413         return WERR_OK;
7414 }
7415
7416 /****************************************************************************
7417 ****************************************************************************/
7418
7419 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7420 {
7421         UNISTR2 *uni_srv_name = &q_u->server_name;
7422         uint32 level = q_u->level;
7423         SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7424         DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7425         SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7426         uint32 user_switch = q_u->user_switch;
7427         SPOOL_USER_CTR *user = &q_u->user_ctr;
7428         POLICY_HND *handle = &r_u->handle;
7429
7430         switch (level) {
7431                 case 1:
7432                         /* we don't handle yet */
7433                         /* but I know what to do ... */
7434                         return WERR_UNKNOWN_LEVEL;
7435                 case 2:
7436                         return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7437                                                             devmode, sdb,
7438                                                             user_switch, user, handle);
7439                 default:
7440                         return WERR_UNKNOWN_LEVEL;
7441         }
7442 }
7443
7444 /****************************************************************************
7445 ****************************************************************************/
7446
7447 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7448 {
7449         uint32 level = q_u->level;
7450         SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7451         WERROR err = WERR_OK;
7452         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7453         struct current_user user;
7454         fstring driver_name;
7455         uint32 version;
7456
7457         ZERO_STRUCT(driver);
7458
7459         get_current_user(&user, p);
7460         
7461         if (!convert_printer_driver_info(info, &driver, level)) {
7462                 err = WERR_NOMEM;
7463                 goto done;
7464         }
7465
7466         DEBUG(5,("Cleaning driver's information\n"));
7467         err = clean_up_driver_struct(driver, level, &user);
7468         if (!W_ERROR_IS_OK(err))
7469                 goto done;
7470
7471         DEBUG(5,("Moving driver to final destination\n"));
7472         if(!move_driver_to_download_area(driver, level, &user, &err)) {
7473                 if (W_ERROR_IS_OK(err))
7474                         err = WERR_ACCESS_DENIED;
7475                 goto done;
7476         }
7477
7478         if (add_a_printer_driver(driver, level)!=0) {
7479                 err = WERR_ACCESS_DENIED;
7480                 goto done;
7481         }
7482
7483         /* BEGIN_ADMIN_LOG */
7484         switch(level) {
7485             case 3:
7486                 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7487                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7488                         driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7489                 break;
7490             case 6:   
7491                 fstrcpy(driver_name, driver.info_6->name ?  driver.info_6->name : "");
7492                 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7493                         driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7494                 break;
7495         }
7496         /* END_ADMIN_LOG */
7497
7498         /* 
7499          * I think this is where he DrvUpgradePrinter() hook would be
7500          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7501          * server.  Right now, we just need to send ourselves a message
7502          * to update each printer bound to this driver.   --jerry       
7503          */
7504          
7505         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7506                 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7507                         driver_name));
7508         }
7509
7510         /*
7511          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7512          * decide if the driver init data should be deleted. The rules are:
7513          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7514          *  2) delete init data only if there is no 2k/Xp driver
7515          *  3) always delete init data
7516          * The generalized rule is always use init data from the highest order driver.
7517          * It is necessary to follow the driver install by an initialization step to
7518          * finish off this process.
7519         */
7520         if (level == 3)
7521                 version = driver.info_3->cversion;
7522         else if (level == 6)
7523                 version = driver.info_6->version;
7524         else
7525                 version = -1;
7526         switch (version) {
7527                 /*
7528                  * 9x printer driver - never delete init data
7529                 */
7530                 case 0: 
7531                         DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7532                                         driver_name));
7533                         break;
7534                 
7535                 /*
7536                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7537                  * there is no 2k/Xp driver init data for this driver name.
7538                 */
7539                 case 2:
7540                 {
7541                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7542
7543                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7544                                 /*
7545                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7546                                 */
7547                                 if (!del_driver_init(driver_name))
7548                                         DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7549                         } else {
7550                                 /*
7551                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7552                                 */
7553                                 free_a_printer_driver(driver1,3);
7554                                 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", 
7555                                                 driver_name));
7556                         }
7557                 }
7558                 break;
7559
7560                 /*
7561                  * 2k or Xp printer driver - always delete init data
7562                 */
7563                 case 3: 
7564                         if (!del_driver_init(driver_name))
7565                                 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7566                         break;
7567
7568                 default:
7569                         DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7570                         break;
7571         }
7572
7573         
7574 done:
7575         free_a_printer_driver(driver, level);
7576         return err;
7577 }
7578
7579 /********************************************************************
7580  * spoolss_addprinterdriverex
7581  ********************************************************************/
7582
7583 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7584 {
7585         SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7586         SPOOL_R_ADDPRINTERDRIVER r_u_local;
7587         
7588         /* 
7589          * we only support the semantics of AddPrinterDriver()
7590          * i.e. only copy files that are newer than existing ones
7591          */
7592         
7593         if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7594                 return WERR_ACCESS_DENIED;
7595         
7596         ZERO_STRUCT(q_u_local);
7597         ZERO_STRUCT(r_u_local);
7598
7599         /* just pass the information off to _spoolss_addprinterdriver() */
7600         q_u_local.server_name_ptr = q_u->server_name_ptr;
7601         copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7602         q_u_local.level = q_u->level;
7603         memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7604         
7605         return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7606 }
7607
7608 /****************************************************************************
7609 ****************************************************************************/
7610
7611 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7612 {
7613         init_unistr(&info->name, name);
7614 }
7615
7616 /****************************************************************************
7617 ****************************************************************************/
7618
7619 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
7620 {
7621         pstring path;
7622         pstring long_archi;
7623         const char *short_archi;
7624         DRIVER_DIRECTORY_1 *info=NULL;
7625
7626         unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7627
7628         if (!(short_archi = get_short_archi(long_archi)))
7629                 return WERR_INVALID_ENVIRONMENT;
7630
7631         if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
7632                 return WERR_NOMEM;
7633
7634         slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi);
7635
7636         DEBUG(4,("printer driver directory: [%s]\n", path));
7637
7638         fill_driverdir_1(info, path);
7639         
7640         *needed += spoolss_size_driverdir_info_1(info);
7641
7642         if (!alloc_buffer_size(buffer, *needed)) {
7643                 SAFE_FREE(info);
7644                 return WERR_INSUFFICIENT_BUFFER;
7645         }
7646
7647         smb_io_driverdir_1("", buffer, info, 0);
7648
7649         SAFE_FREE(info);
7650         
7651         if (*needed > offered)
7652                 return WERR_INSUFFICIENT_BUFFER;
7653
7654         return WERR_OK;
7655 }
7656
7657 /****************************************************************************
7658 ****************************************************************************/
7659
7660 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7661 {
7662         UNISTR2 *name = &q_u->name;
7663         UNISTR2 *uni_environment = &q_u->environment;
7664         uint32 level = q_u->level;
7665         NEW_BUFFER *buffer = NULL;
7666         uint32 offered = q_u->offered;
7667         uint32 *needed = &r_u->needed;
7668
7669         /* that's an [in out] buffer */
7670         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
7671         buffer = r_u->buffer;
7672
7673         DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7674
7675         *needed=0;
7676
7677         switch(level) {
7678         case 1:
7679                 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7680         default:
7681                 return WERR_UNKNOWN_LEVEL;
7682         }
7683 }
7684         
7685 /****************************************************************************
7686 ****************************************************************************/
7687
7688 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7689 {
7690         POLICY_HND *handle = &q_u->handle;
7691         uint32 idx               = q_u->index;
7692         uint32 in_value_len      = q_u->valuesize;
7693         uint32 in_data_len       = q_u->datasize;
7694         uint32 *out_max_value_len = &r_u->valuesize;
7695         uint16 **out_value       = &r_u->value;
7696         uint32 *out_value_len    = &r_u->realvaluesize;
7697         uint32 *out_type         = &r_u->type;
7698         uint32 *out_max_data_len = &r_u->datasize;
7699         uint8  **data_out        = &r_u->data;
7700         uint32 *out_data_len     = &r_u->realdatasize;
7701
7702         NT_PRINTER_INFO_LEVEL *printer = NULL;
7703         
7704         uint32          biggest_valuesize;
7705         uint32          biggest_datasize;
7706         uint32          data_len;
7707         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
7708         int             snum;
7709         WERROR          result;
7710         REGISTRY_VALUE  *val = NULL;
7711         NT_PRINTER_DATA *p_data;
7712         int             i, key_index, num_values;
7713         int             name_length;
7714         
7715         ZERO_STRUCT( printer );
7716         
7717         *out_type = 0;
7718
7719         *out_max_data_len = 0;
7720         *data_out         = NULL;
7721         *out_data_len     = 0;
7722
7723         DEBUG(5,("spoolss_enumprinterdata\n"));
7724
7725         if (!Printer) {
7726                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7727                 return WERR_BADFID;
7728         }
7729
7730         if (!get_printer_snum(p,handle, &snum))
7731                 return WERR_BADFID;
7732         
7733         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7734         if (!W_ERROR_IS_OK(result))
7735                 return result;
7736                 
7737         p_data = &printer->info_2->data;        
7738         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7739
7740         result = WERR_OK;
7741
7742         /*
7743          * The NT machine wants to know the biggest size of value and data
7744          *
7745          * cf: MSDN EnumPrinterData remark section
7746          */
7747          
7748         if ( !in_value_len && !in_data_len && (key_index != -1) ) 
7749         {
7750                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7751
7752                 biggest_valuesize = 0;
7753                 biggest_datasize  = 0;
7754                                 
7755                 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7756                 
7757                 for ( i=0; i<num_values; i++ )
7758                 {
7759                         val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7760                         
7761                         name_length = strlen(val->valuename);
7762                         if ( strlen(val->valuename) > biggest_valuesize ) 
7763                                 biggest_valuesize = name_length;
7764                                 
7765                         if ( val->size > biggest_datasize )
7766                                 biggest_datasize = val->size;
7767                                 
7768                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, 
7769                                 biggest_datasize));
7770                 }
7771
7772                 /* the value is an UNICODE string but real_value_size is the length 
7773                    in bytes including the trailing 0 */
7774                    
7775                 *out_value_len = 2 * (1+biggest_valuesize);
7776                 *out_data_len  = biggest_datasize;
7777
7778                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7779
7780                 goto done;
7781         }
7782         
7783         /*
7784          * the value len is wrong in NT sp3
7785          * that's the number of bytes not the number of unicode chars
7786          */
7787         
7788         if ( key_index != -1 )
7789                 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7790
7791         if ( !val ) 
7792         {
7793
7794                 /* out_value should default to "" or else NT4 has
7795                    problems unmarshalling the response */
7796
7797                 *out_max_value_len=(in_value_len/sizeof(uint16));
7798                 
7799                 if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7800                 {
7801                         result = WERR_NOMEM;
7802                         goto done;
7803                 }
7804
7805                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7806
7807                 /* the data is counted in bytes */
7808                 
7809                 *out_max_data_len = in_data_len;
7810                 *out_data_len     = in_data_len;
7811                 
7812                 /* only allocate when given a non-zero data_len */
7813                 
7814                 if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7815                 {
7816                         result = WERR_NOMEM;
7817                         goto done;
7818                 }
7819
7820                 result = WERR_NO_MORE_ITEMS;
7821         }
7822         else 
7823         {
7824                 /*
7825                  * the value is:
7826                  * - counted in bytes in the request
7827                  * - counted in UNICODE chars in the max reply
7828                  * - counted in bytes in the real size
7829                  *
7830                  * take a pause *before* coding not *during* coding
7831                  */
7832         
7833                 /* name */
7834                 *out_max_value_len=(in_value_len/sizeof(uint16));
7835                 if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL ) 
7836                 {
7837                         result = WERR_NOMEM;
7838                         goto done;
7839                 }
7840         
7841                 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7842
7843                 /* type */
7844                 
7845                 *out_type = regval_type( val );
7846
7847                 /* data - counted in bytes */
7848
7849                 *out_max_data_len = in_data_len;
7850                 if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) 
7851                 {
7852                         result = WERR_NOMEM;
7853                         goto done;
7854                 }
7855                 data_len = (size_t)regval_size(val);
7856                 memcpy( *data_out, regval_data_p(val), data_len );
7857                 *out_data_len = data_len;
7858         }
7859
7860 done:
7861         free_a_printer(&printer, 2);
7862         return result;
7863 }
7864
7865 /****************************************************************************
7866 ****************************************************************************/
7867
7868 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7869 {
7870         POLICY_HND              *handle = &q_u->handle;
7871         UNISTR2                 *value = &q_u->value;
7872         uint32                  type = q_u->type;
7873         uint8                   *data = q_u->data;
7874         uint32                  real_len = q_u->real_len;
7875
7876         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7877         int                     snum=0;
7878         WERROR                  status = WERR_OK;
7879         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
7880         fstring                 valuename;
7881         
7882         DEBUG(5,("spoolss_setprinterdata\n"));
7883
7884         if (!Printer) {
7885                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7886                 return WERR_BADFID;
7887         }
7888
7889         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7890                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7891                 return WERR_INVALID_PARAM;
7892         }
7893
7894         if (!get_printer_snum(p,handle, &snum))
7895                 return WERR_BADFID;
7896
7897         /* 
7898          * Access check : NT returns "access denied" if you make a 
7899          * SetPrinterData call without the necessary privildge.
7900          * we were originally returning OK if nothing changed
7901          * which made Win2k issue **a lot** of SetPrinterData
7902          * when connecting to a printer  --jerry
7903          */
7904
7905         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
7906         {
7907                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7908                 status = WERR_ACCESS_DENIED;
7909                 goto done;
7910         }
7911
7912         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7913         if (!W_ERROR_IS_OK(status))
7914                 return status;
7915
7916         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
7917         
7918         /*
7919          * When client side code sets a magic printer data key, detect it and save
7920          * the current printer data and the magic key's data (its the DEVMODE) for
7921          * future printer/driver initializations.
7922          */
7923         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
7924         {
7925                 /* Set devmode and printer initialization info */
7926                 status = save_driver_init( printer, 2, data, real_len );
7927         
7928                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
7929         }
7930         else 
7931         {
7932         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
7933                                         type, data, real_len );
7934                 if ( W_ERROR_IS_OK(status) )
7935                         status = mod_a_printer(*printer, 2);
7936         }
7937
7938 done:
7939         free_a_printer(&printer, 2);
7940
7941         return status;
7942 }
7943
7944 /****************************************************************************
7945 ****************************************************************************/
7946
7947 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
7948 {
7949         POLICY_HND      *handle = &q_u->handle;
7950         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7951         int             snum;
7952         
7953         DEBUG(5,("_spoolss_resetprinter\n"));
7954
7955         /*
7956          * All we do is to check to see if the handle and queue is valid.
7957          * This call really doesn't mean anything to us because we only
7958          * support RAW printing.   --jerry
7959          */
7960          
7961         if (!Printer) {
7962                 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7963                 return WERR_BADFID;
7964         }
7965
7966         if (!get_printer_snum(p,handle, &snum))
7967                 return WERR_BADFID;
7968
7969
7970         /* blindly return success */    
7971         return WERR_OK;
7972 }
7973
7974
7975 /****************************************************************************
7976 ****************************************************************************/
7977
7978 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
7979 {
7980         POLICY_HND      *handle = &q_u->handle;
7981         UNISTR2         *value = &q_u->valuename;
7982
7983         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7984         int             snum=0;
7985         WERROR          status = WERR_OK;
7986         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
7987         pstring         valuename;
7988         
7989         DEBUG(5,("spoolss_deleteprinterdata\n"));
7990         
7991         if (!Printer) {
7992                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7993                 return WERR_BADFID;
7994         }
7995
7996         if (!get_printer_snum(p, handle, &snum))
7997                 return WERR_BADFID;
7998
7999         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8000                 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8001                 return WERR_ACCESS_DENIED;
8002         }
8003
8004         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8005         if (!W_ERROR_IS_OK(status))
8006                 return status;
8007
8008         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8009
8010         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8011         
8012         if ( W_ERROR_IS_OK(status) )
8013                 mod_a_printer( *printer, 2 );
8014
8015         free_a_printer(&printer, 2);
8016
8017         return status;
8018 }
8019
8020 /****************************************************************************
8021 ****************************************************************************/
8022
8023 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8024 {
8025         POLICY_HND *handle = &q_u->handle;
8026         FORM *form = &q_u->form;
8027         nt_forms_struct tmpForm;
8028         int snum;
8029         WERROR status = WERR_OK;
8030         NT_PRINTER_INFO_LEVEL *printer = NULL;
8031
8032         int count=0;
8033         nt_forms_struct *list=NULL;
8034         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8035
8036         DEBUG(5,("spoolss_addform\n"));
8037
8038         if (!Printer) {
8039                 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8040                 return WERR_BADFID;
8041         }
8042         
8043         
8044         /* forms can be added on printer of on the print server handle */
8045         
8046         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8047         {
8048                 if (!get_printer_snum(p,handle, &snum))
8049                         return WERR_BADFID;
8050          
8051                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8052                 if (!W_ERROR_IS_OK(status))
8053                         goto done;
8054         }
8055
8056         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8057                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8058                 status = WERR_ACCESS_DENIED;
8059                 goto done;
8060         }
8061         
8062         /* can't add if builtin */
8063         
8064         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8065                 status = WERR_ALREADY_EXISTS;
8066                 goto done;
8067         }
8068
8069         count = get_ntforms(&list);
8070         
8071         if(!add_a_form(&list, form, &count)) {
8072                 status =  WERR_NOMEM;
8073                 goto done;
8074         }
8075         
8076         write_ntforms(&list, count);
8077         
8078         /*
8079          * ChangeID must always be set if this is a printer
8080          */
8081          
8082         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8083                 status = mod_a_printer(*printer, 2);
8084         
8085 done:
8086         if ( printer )
8087                 free_a_printer(&printer, 2);
8088         SAFE_FREE(list);
8089
8090         return status;
8091 }
8092
8093 /****************************************************************************
8094 ****************************************************************************/
8095
8096 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8097 {
8098         POLICY_HND *handle = &q_u->handle;
8099         UNISTR2 *form_name = &q_u->name;
8100         nt_forms_struct tmpForm;
8101         int count=0;
8102         nt_forms_struct *list=NULL;
8103         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8104         int snum;
8105         WERROR status = WERR_OK;
8106         NT_PRINTER_INFO_LEVEL *printer = NULL;
8107
8108         DEBUG(5,("spoolss_deleteform\n"));
8109
8110         if (!Printer) {
8111                 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8112                 return WERR_BADFID;
8113         }
8114
8115         /* forms can be deleted on printer of on the print server handle */
8116         
8117         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8118         {
8119                 if (!get_printer_snum(p,handle, &snum))
8120                         return WERR_BADFID;
8121          
8122                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8123                 if (!W_ERROR_IS_OK(status))
8124                         goto done;
8125         }
8126
8127         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8128                 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8129                 status = WERR_ACCESS_DENIED;
8130                 goto done;
8131         }
8132
8133         /* can't delete if builtin */
8134         
8135         if (get_a_builtin_ntform(form_name,&tmpForm)) {
8136                 status = WERR_INVALID_PARAM;
8137                 goto done;
8138         }
8139
8140         count = get_ntforms(&list);
8141         
8142         if ( !delete_a_form(&list, form_name, &count, &status ))
8143                 goto done;
8144
8145         /*
8146          * ChangeID must always be set if this is a printer
8147          */
8148          
8149         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8150                 status = mod_a_printer(*printer, 2);
8151         
8152 done:
8153         if ( printer )
8154                 free_a_printer(&printer, 2);
8155         SAFE_FREE(list);
8156
8157         return status;
8158 }
8159
8160 /****************************************************************************
8161 ****************************************************************************/
8162
8163 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8164 {
8165         POLICY_HND *handle = &q_u->handle;
8166         FORM *form = &q_u->form;
8167         nt_forms_struct tmpForm;
8168         int snum;
8169         WERROR status = WERR_OK;
8170         NT_PRINTER_INFO_LEVEL *printer = NULL;
8171
8172         int count=0;
8173         nt_forms_struct *list=NULL;
8174         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8175
8176         DEBUG(5,("spoolss_setform\n"));
8177
8178         if (!Printer) {
8179                 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8180                 return WERR_BADFID;
8181         }
8182
8183         /* forms can be modified on printer of on the print server handle */
8184         
8185         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8186         {
8187                 if (!get_printer_snum(p,handle, &snum))
8188                         return WERR_BADFID;
8189          
8190                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8191                 if (!W_ERROR_IS_OK(status))
8192                         goto done;
8193         }
8194
8195         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8196                 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8197                 status = WERR_ACCESS_DENIED;
8198                 goto done;
8199         }
8200
8201         /* can't set if builtin */
8202         if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8203                 status = WERR_INVALID_PARAM;
8204                 goto done;
8205         }
8206
8207         count = get_ntforms(&list);
8208         update_a_form(&list, form, count);
8209         write_ntforms(&list, count);
8210
8211         /*
8212          * ChangeID must always be set if this is a printer
8213          */
8214          
8215         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8216                 status = mod_a_printer(*printer, 2);
8217         
8218         
8219 done:
8220         if ( printer )
8221                 free_a_printer(&printer, 2);
8222         SAFE_FREE(list);
8223
8224         return status;
8225 }
8226
8227 /****************************************************************************
8228  enumprintprocessors level 1.
8229 ****************************************************************************/
8230
8231 static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8232 {
8233         PRINTPROCESSOR_1 *info_1=NULL;
8234         
8235         if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
8236                 return WERR_NOMEM;
8237
8238         (*returned) = 0x1;
8239         
8240         init_unistr(&info_1->name, "winprint");
8241
8242         *needed += spoolss_size_printprocessor_info_1(info_1);
8243
8244         if (!alloc_buffer_size(buffer, *needed))
8245                 return WERR_INSUFFICIENT_BUFFER;
8246
8247         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8248
8249         SAFE_FREE(info_1);
8250
8251         if (*needed > offered) {
8252                 *returned=0;
8253                 return WERR_INSUFFICIENT_BUFFER;
8254         }
8255
8256         return WERR_OK;
8257 }
8258
8259 /****************************************************************************
8260 ****************************************************************************/
8261
8262 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8263 {
8264         uint32 level = q_u->level;
8265         NEW_BUFFER *buffer = NULL;
8266         uint32 offered = q_u->offered;
8267         uint32 *needed = &r_u->needed;
8268         uint32 *returned = &r_u->returned;
8269
8270         /* that's an [in out] buffer */
8271         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8272         buffer = r_u->buffer;
8273
8274         DEBUG(5,("spoolss_enumprintprocessors\n"));
8275
8276         /*
8277          * Enumerate the print processors ...
8278          *
8279          * Just reply with "winprint", to keep NT happy
8280          * and I can use my nice printer checker.
8281          */
8282         
8283         *returned=0;
8284         *needed=0;
8285         
8286         switch (level) {
8287         case 1:
8288                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8289         default:
8290                 return WERR_UNKNOWN_LEVEL;
8291         }
8292 }
8293
8294 /****************************************************************************
8295  enumprintprocdatatypes level 1.
8296 ****************************************************************************/
8297
8298 static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8299 {
8300         PRINTPROCDATATYPE_1 *info_1=NULL;
8301         
8302         if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
8303                 return WERR_NOMEM;
8304
8305         (*returned) = 0x1;
8306         
8307         init_unistr(&info_1->name, "RAW");
8308
8309         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8310
8311         if (!alloc_buffer_size(buffer, *needed))
8312                 return WERR_INSUFFICIENT_BUFFER;
8313
8314         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8315
8316         SAFE_FREE(info_1);
8317
8318         if (*needed > offered) {
8319                 *returned=0;
8320                 return WERR_INSUFFICIENT_BUFFER;
8321         }
8322
8323         return WERR_OK;
8324 }
8325
8326 /****************************************************************************
8327 ****************************************************************************/
8328
8329 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8330 {
8331         uint32 level = q_u->level;
8332         NEW_BUFFER *buffer = NULL;
8333         uint32 offered = q_u->offered;
8334         uint32 *needed = &r_u->needed;
8335         uint32 *returned = &r_u->returned;
8336
8337         /* that's an [in out] buffer */
8338         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8339         buffer = r_u->buffer;
8340
8341         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8342         
8343         *returned=0;
8344         *needed=0;
8345         
8346         switch (level) {
8347         case 1:
8348                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8349         default:
8350                 return WERR_UNKNOWN_LEVEL;
8351         }
8352 }
8353
8354 /****************************************************************************
8355  enumprintmonitors level 1.
8356 ****************************************************************************/
8357
8358 static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8359 {
8360         PRINTMONITOR_1 *info_1=NULL;
8361         
8362         if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
8363                 return WERR_NOMEM;
8364
8365         (*returned) = 0x1;
8366         
8367         init_unistr(&info_1->name, "Local Port");
8368
8369         *needed += spoolss_size_printmonitor_info_1(info_1);
8370
8371         if (!alloc_buffer_size(buffer, *needed))
8372                 return WERR_INSUFFICIENT_BUFFER;
8373
8374         smb_io_printmonitor_info_1("", buffer, info_1, 0);
8375
8376         SAFE_FREE(info_1);
8377
8378         if (*needed > offered) {
8379                 *returned=0;
8380                 return WERR_INSUFFICIENT_BUFFER;
8381         }
8382
8383         return WERR_OK;
8384 }
8385
8386 /****************************************************************************
8387  enumprintmonitors level 2.
8388 ****************************************************************************/
8389
8390 static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8391 {
8392         PRINTMONITOR_2 *info_2=NULL;
8393         
8394         if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
8395                 return WERR_NOMEM;
8396
8397         (*returned) = 0x1;
8398         
8399         init_unistr(&info_2->name, "Local Port");
8400         init_unistr(&info_2->environment, "Windows NT X86");
8401         init_unistr(&info_2->dll_name, "localmon.dll");
8402
8403         *needed += spoolss_size_printmonitor_info_2(info_2);
8404
8405         if (!alloc_buffer_size(buffer, *needed))
8406                 return WERR_INSUFFICIENT_BUFFER;
8407
8408         smb_io_printmonitor_info_2("", buffer, info_2, 0);
8409
8410         SAFE_FREE(info_2);
8411
8412         if (*needed > offered) {
8413                 *returned=0;
8414                 return WERR_INSUFFICIENT_BUFFER;
8415         }
8416
8417         return WERR_OK;
8418 }
8419
8420 /****************************************************************************
8421 ****************************************************************************/
8422
8423 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8424 {
8425         uint32 level = q_u->level;
8426         NEW_BUFFER *buffer = NULL;
8427         uint32 offered = q_u->offered;
8428         uint32 *needed = &r_u->needed;
8429         uint32 *returned = &r_u->returned;
8430
8431         /* that's an [in out] buffer */
8432         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8433         buffer = r_u->buffer;
8434
8435         DEBUG(5,("spoolss_enumprintmonitors\n"));
8436
8437         /*
8438          * Enumerate the print monitors ...
8439          *
8440          * Just reply with "Local Port", to keep NT happy
8441          * and I can use my nice printer checker.
8442          */
8443         
8444         *returned=0;
8445         *needed=0;
8446         
8447         switch (level) {
8448         case 1:
8449                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8450         case 2:
8451                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8452         default:
8453                 return WERR_UNKNOWN_LEVEL;
8454         }
8455 }
8456
8457 /****************************************************************************
8458 ****************************************************************************/
8459
8460 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8461 {
8462         int i=0;
8463         BOOL found=False;
8464         JOB_INFO_1 *info_1=NULL;
8465
8466         info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
8467
8468         if (info_1 == NULL) {
8469                 return WERR_NOMEM;
8470         }
8471                 
8472         for (i=0; i<count && found==False; i++) { 
8473                 if ((*queue)[i].job==(int)jobid)
8474                         found=True;
8475         }
8476         
8477         if (found==False) {
8478                 SAFE_FREE(info_1);
8479                 /* NT treats not found as bad param... yet another bad choice */
8480                 return WERR_INVALID_PARAM;
8481         }
8482         
8483         fill_job_info_1(info_1, &((*queue)[i-1]), i, snum);
8484         
8485         *needed += spoolss_size_job_info_1(info_1);
8486
8487         if (!alloc_buffer_size(buffer, *needed)) {
8488                 SAFE_FREE(info_1);
8489                 return WERR_INSUFFICIENT_BUFFER;
8490         }
8491
8492         smb_io_job_info_1("", buffer, info_1, 0);
8493
8494         SAFE_FREE(info_1);
8495
8496         if (*needed > offered)
8497                 return WERR_INSUFFICIENT_BUFFER;
8498
8499         return WERR_OK;
8500 }
8501
8502 /****************************************************************************
8503 ****************************************************************************/
8504
8505 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
8506 {
8507         int             i = 0;
8508         BOOL            found = False;
8509         JOB_INFO_2      *info_2;
8510         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8511         WERROR          ret;
8512         DEVICEMODE      *devmode = NULL;
8513         NT_DEVICEMODE   *nt_devmode = NULL;
8514
8515         info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
8516
8517         ZERO_STRUCTP(info_2);
8518
8519         if (info_2 == NULL) {
8520                 ret = WERR_NOMEM;
8521                 goto done;
8522         }
8523
8524         for ( i=0; i<count && found==False; i++ ) 
8525         {
8526                 if ((*queue)[i].job == (int)jobid)
8527                         found = True;
8528         }
8529         
8530         if ( !found ) 
8531         {
8532                 /* NT treats not found as bad param... yet another bad
8533                    choice */
8534                 ret = WERR_INVALID_PARAM;
8535                 goto done;
8536         }
8537         
8538         ret = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
8539         if (!W_ERROR_IS_OK(ret))
8540                 goto done;
8541         
8542         /* 
8543          * if the print job does not have a DEVMODE associated with it, 
8544          * just use the one for the printer. A NULL devicemode is not
8545          *  a failure condition
8546          */
8547          
8548         if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
8549                 devmode = construct_dev_mode(snum);
8550         else {
8551                 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
8552                         ZERO_STRUCTP( devmode );
8553                         convert_nt_devicemode( devmode, nt_devmode );
8554                 }
8555         }
8556         
8557         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8558         
8559         *needed += spoolss_size_job_info_2(info_2);
8560
8561         if (!alloc_buffer_size(buffer, *needed)) {
8562                 ret = WERR_INSUFFICIENT_BUFFER;
8563                 goto done;
8564         }
8565
8566         smb_io_job_info_2("", buffer, info_2, 0);
8567
8568         if (*needed > offered) {
8569                 ret = WERR_INSUFFICIENT_BUFFER;
8570                 goto done;
8571         }
8572
8573         ret = WERR_OK;
8574         
8575  done:
8576         /* Cleanup allocated memory */
8577
8578         free_job_info_2(info_2);        /* Also frees devmode */
8579         SAFE_FREE(info_2);
8580         free_a_printer(&ntprinter, 2);
8581
8582         return ret;
8583 }
8584
8585 /****************************************************************************
8586 ****************************************************************************/
8587
8588 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8589 {
8590         POLICY_HND *handle = &q_u->handle;
8591         uint32 jobid = q_u->jobid;
8592         uint32 level = q_u->level;
8593         NEW_BUFFER *buffer = NULL;
8594         uint32 offered = q_u->offered;
8595         uint32 *needed = &r_u->needed;
8596         WERROR          wstatus = WERR_OK;
8597
8598         int snum;
8599         int count;
8600         print_queue_struct      *queue = NULL;
8601         print_status_struct prt_status;
8602
8603         /* that's an [in out] buffer */
8604         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
8605         buffer = r_u->buffer;
8606
8607         DEBUG(5,("spoolss_getjob\n"));
8608         
8609         *needed = 0;
8610         
8611         if (!get_printer_snum(p, handle, &snum))
8612                 return WERR_BADFID;
8613         
8614         count = print_queue_status(snum, &queue, &prt_status);
8615         
8616         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8617                      count, prt_status.status, prt_status.message));
8618                 
8619         switch ( level ) {
8620         case 1:
8621                         wstatus = getjob_level_1(&queue, count, snum, jobid, 
8622                                 buffer, offered, needed);
8623                         break;
8624         case 2:
8625                         wstatus = getjob_level_2(&queue, count, snum, jobid, 
8626                                 buffer, offered, needed);
8627                         break;
8628         default:
8629                         wstatus = WERR_UNKNOWN_LEVEL;
8630                         break;
8631         }
8632         
8633         SAFE_FREE(queue);
8634         return wstatus;
8635 }
8636
8637 /********************************************************************
8638  spoolss_getprinterdataex
8639  
8640  From MSDN documentation of GetPrinterDataEx: pass request
8641  to GetPrinterData if key is "PrinterDriverData".
8642  ********************************************************************/
8643
8644 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8645 {
8646         POLICY_HND      *handle = &q_u->handle;
8647         uint32          in_size = q_u->size;
8648         uint32          *type = &r_u->type;
8649         uint32          *out_size = &r_u->size;
8650         uint8           **data = &r_u->data;
8651         uint32          *needed = &r_u->needed;
8652         fstring         keyname, valuename;
8653         
8654         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8655         
8656         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8657         int                     snum = 0;
8658         WERROR                  status = WERR_OK;
8659
8660         DEBUG(4,("_spoolss_getprinterdataex\n"));
8661
8662         unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8663         unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8664         
8665         DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
8666                 keyname, valuename));
8667
8668         /* in case of problem, return some default values */
8669         
8670         *needed   = 0;
8671         *type     = 0;
8672         *out_size = in_size;
8673
8674         if (!Printer) {
8675                 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8676                 status = WERR_BADFID;
8677                 goto done;
8678         }
8679
8680         /* Is the handle to a printer or to the server? */
8681
8682         if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8683                 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8684                 status = WERR_INVALID_PARAM;
8685                 goto done;
8686         }
8687         
8688         if ( !get_printer_snum(p,handle, &snum) )
8689                 return WERR_BADFID;
8690
8691         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8692         if ( !W_ERROR_IS_OK(status) )
8693                 goto done;
8694
8695         /* check to see if the keyname is valid */
8696         if ( !strlen(keyname) ) {
8697                 status = WERR_INVALID_PARAM;
8698                 goto done;
8699         }
8700         
8701         if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8702                 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8703                 free_a_printer( &printer, 2 );
8704                 status = WERR_BADFILE;
8705                 goto done;
8706         }
8707         
8708         /* When given a new keyname, we should just create it */
8709
8710         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8711         
8712         if (*needed > *out_size)
8713                 status = WERR_MORE_DATA;
8714
8715 done:
8716         if ( !W_ERROR_IS_OK(status) ) 
8717         {
8718                 DEBUG(5, ("error: allocating %d\n", *out_size));
8719                 
8720                 /* reply this param doesn't exist */
8721                 
8722                 if ( *out_size ) 
8723                 {
8724                         if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8725                                 status = WERR_NOMEM;
8726                                 goto done;
8727                         }
8728                 } 
8729                 else {
8730                         *data = NULL;
8731         }
8732         }
8733         
8734         if ( printer )
8735         free_a_printer( &printer, 2 );
8736         
8737         return status;
8738 }
8739
8740 /********************************************************************
8741  * spoolss_setprinterdataex
8742  ********************************************************************/
8743
8744 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8745 {
8746         POLICY_HND              *handle = &q_u->handle; 
8747         uint32                  type = q_u->type;
8748         uint8                   *data = q_u->data;
8749         uint32                  real_len = q_u->real_len;
8750
8751         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8752         int                     snum = 0;
8753         WERROR                  status = WERR_OK;
8754         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
8755         fstring                 valuename;
8756         fstring                 keyname;
8757         char                    *oid_string;
8758         
8759         DEBUG(4,("_spoolss_setprinterdataex\n"));
8760
8761         /* From MSDN documentation of SetPrinterDataEx: pass request to
8762            SetPrinterData if key is "PrinterDriverData" */
8763
8764         if (!Printer) {
8765                 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8766                 return WERR_BADFID;
8767         }
8768
8769         if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8770                 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8771                 return WERR_INVALID_PARAM;
8772         }
8773
8774         if ( !get_printer_snum(p,handle, &snum) )
8775                 return WERR_BADFID;
8776
8777         /* 
8778          * Access check : NT returns "access denied" if you make a 
8779          * SetPrinterData call without the necessary privildge.
8780          * we were originally returning OK if nothing changed
8781          * which made Win2k issue **a lot** of SetPrinterData
8782          * when connecting to a printer  --jerry
8783          */
8784
8785         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
8786         {
8787                 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8788                 return WERR_ACCESS_DENIED;
8789         }
8790
8791         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8792         if (!W_ERROR_IS_OK(status))
8793                 return status;
8794
8795         unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8796         unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8797         
8798         /* check for OID in valuename */
8799         
8800         if ( (oid_string = strchr( valuename, ',' )) != NULL )
8801         {
8802                 *oid_string = '\0';
8803                 oid_string++;
8804         }
8805
8806         /* save the registry data */
8807         
8808         status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
8809         
8810         if ( W_ERROR_IS_OK(status) )
8811         {
8812                 /* save the OID if one was specified */
8813                 if ( oid_string ) {
8814                         fstrcat( keyname, "\\" );
8815                         fstrcat( keyname, SPOOL_OID_KEY );
8816                 
8817                         /* 
8818                          * I'm not checking the status here on purpose.  Don't know 
8819                          * if this is right, but I'm returning the status from the 
8820                          * previous set_printer_dataex() call.  I have no idea if 
8821                          * this is right.    --jerry
8822                          */
8823                  
8824                         set_printer_dataex( printer, keyname, valuename, 
8825                                             REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
8826                 }
8827         
8828                 status = mod_a_printer(*printer, 2);
8829         }
8830                 
8831         free_a_printer(&printer, 2);
8832
8833         return status;
8834 }
8835
8836
8837 /********************************************************************
8838  * spoolss_deleteprinterdataex
8839  ********************************************************************/
8840
8841 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8842 {
8843         POLICY_HND      *handle = &q_u->handle;
8844         UNISTR2         *value = &q_u->valuename;
8845         UNISTR2         *key = &q_u->keyname;
8846
8847         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8848         int             snum=0;
8849         WERROR          status = WERR_OK;
8850         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8851         pstring         valuename, keyname;
8852         
8853         DEBUG(5,("spoolss_deleteprinterdataex\n"));
8854         
8855         if (!Printer) {
8856                 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8857                 return WERR_BADFID;
8858         }
8859
8860         if (!get_printer_snum(p, handle, &snum))
8861                 return WERR_BADFID;
8862
8863         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8864                 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8865                 return WERR_ACCESS_DENIED;
8866         }
8867
8868         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8869         if (!W_ERROR_IS_OK(status))
8870                 return status;
8871
8872         unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8873         unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
8874
8875         status = delete_printer_dataex( printer, keyname, valuename );
8876
8877         if ( W_ERROR_IS_OK(status) )
8878                 mod_a_printer( *printer, 2 );
8879                 
8880         free_a_printer(&printer, 2);
8881
8882         return status;
8883 }
8884
8885 /********************************************************************
8886  * spoolss_enumprinterkey
8887  ********************************************************************/
8888
8889
8890 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
8891 {
8892         fstring         key;
8893         fstring         *keynames = NULL;
8894         uint16          *enumkeys = NULL;
8895         int             num_keys;
8896         int             printerkey_len;
8897         POLICY_HND      *handle = &q_u->handle;
8898         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8899         NT_PRINTER_DATA *data;
8900         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8901         int             snum = 0;
8902         WERROR          status = WERR_BADFILE;
8903         
8904         
8905         DEBUG(4,("_spoolss_enumprinterkey\n"));
8906
8907         if (!Printer) {
8908                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8909                 return WERR_BADFID;
8910         }
8911
8912         if ( !get_printer_snum(p,handle, &snum) )
8913                 return WERR_BADFID;
8914
8915         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8916         if (!W_ERROR_IS_OK(status))
8917                 return status;
8918                 
8919         /* get the list of subkey names */
8920         
8921         unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
8922         data = &printer->info_2->data;
8923
8924         num_keys = get_printer_subkeys( data, key, &keynames );
8925
8926         if ( num_keys == -1 ) {
8927                 status = WERR_BADFILE;
8928                 goto done;
8929         }
8930
8931         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
8932
8933         r_u->needed = printerkey_len*2;
8934
8935         if ( q_u->size < r_u->needed ) {
8936                 status = WERR_MORE_DATA;
8937                 goto done;
8938         }
8939
8940         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
8941                 status = WERR_NOMEM;
8942                 goto done;
8943         }
8944                         
8945         status = WERR_OK;
8946
8947         if ( q_u->size < r_u->needed ) 
8948                 status = WERR_MORE_DATA;
8949
8950 done:
8951         free_a_printer( &printer, 2 );
8952         SAFE_FREE( keynames );
8953         
8954         return status;
8955 }
8956
8957 /********************************************************************
8958  * spoolss_deleteprinterkey
8959  ********************************************************************/
8960
8961 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
8962 {
8963         POLICY_HND              *handle = &q_u->handle;
8964         Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
8965         fstring                 key;
8966         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8967         int                     snum=0;
8968         WERROR                  status;
8969         
8970         DEBUG(5,("spoolss_deleteprinterkey\n"));
8971         
8972         if (!Printer) {
8973                 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8974                 return WERR_BADFID;
8975         }
8976
8977         /* if keyname == NULL, return error */
8978         
8979         if ( !q_u->keyname.buffer )
8980                 return WERR_INVALID_PARAM;
8981                 
8982         if (!get_printer_snum(p, handle, &snum))
8983                 return WERR_BADFID;
8984
8985         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8986                 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8987                 return WERR_ACCESS_DENIED;
8988         }
8989
8990         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8991         if (!W_ERROR_IS_OK(status))
8992                 return status;
8993         
8994         /* delete the key and all subneys */
8995         
8996         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
8997  
8998         status = delete_all_printer_data( printer->info_2, key );       
8999
9000         if ( W_ERROR_IS_OK(status) )
9001                 status = mod_a_printer(*printer, 2);
9002         
9003         free_a_printer( &printer, 2 );
9004         
9005         return status;
9006 }
9007
9008
9009 /********************************************************************
9010  * spoolss_enumprinterdataex
9011  ********************************************************************/
9012
9013 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9014 {
9015         POLICY_HND      *handle = &q_u->handle; 
9016         uint32          in_size = q_u->size;
9017         uint32          num_entries, 
9018                         needed;
9019         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9020         PRINTER_ENUM_VALUES     *enum_values = NULL;
9021         NT_PRINTER_DATA         *p_data;
9022         fstring         key;
9023         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9024         int             snum;
9025         WERROR          result;
9026         int             key_index;
9027         int             i;
9028         REGISTRY_VALUE  *val;
9029         char            *value_name;
9030         int             data_len;
9031         
9032
9033         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9034
9035         if (!Printer) {
9036                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9037                 return WERR_BADFID;
9038         }
9039
9040         /* 
9041          * first check for a keyname of NULL or "".  Win2k seems to send 
9042          * this a lot and we should send back WERR_INVALID_PARAM
9043          * no need to spend time looking up the printer in this case.
9044          * --jerry
9045          */
9046          
9047         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9048         if ( !strlen(key) ) {
9049                 result = WERR_INVALID_PARAM;
9050                 goto done;
9051         }
9052
9053         /* get the printer off of disk */
9054         
9055         if (!get_printer_snum(p,handle, &snum))
9056                 return WERR_BADFID;
9057         
9058         ZERO_STRUCT(printer);
9059         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9060         if (!W_ERROR_IS_OK(result))
9061                 return result;
9062         
9063         /* now look for a match on the key name */
9064         
9065         p_data = &printer->info_2->data;
9066         
9067         unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9068         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9069         {
9070                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9071                 result = WERR_INVALID_PARAM;
9072                 goto done;
9073         }
9074         
9075         result = WERR_OK;
9076         needed = 0;
9077         
9078         /* allocate the memory for the array of pointers -- if necessary */
9079         
9080         num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9081         if ( num_entries )
9082         {
9083                 if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
9084                 {
9085                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9086                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9087                         result = WERR_NOMEM;
9088                         goto done;
9089                 }
9090
9091                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9092         }
9093                 
9094         /* 
9095          * loop through all params and build the array to pass 
9096          * back to the  client 
9097          */
9098          
9099         for ( i=0; i<num_entries; i++ )
9100         {
9101                 /* lookup the registry value */
9102                 
9103                 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9104                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9105
9106                 /* copy the data */
9107                 
9108                 value_name = regval_name( val );
9109                 init_unistr( &enum_values[i].valuename, value_name );
9110                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9111                 enum_values[i].type      = regval_type( val );
9112                 
9113                 data_len = regval_size( val );
9114                 if ( data_len ) {
9115                         if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) ) 
9116                         {
9117                                 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n", 
9118                                         data_len ));
9119                                 result = WERR_NOMEM;
9120                                 goto done;
9121                         }
9122                 }
9123                 enum_values[i].data_len = data_len;
9124
9125                 /* keep track of the size of the array in bytes */
9126                 
9127                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9128         }
9129         
9130         /* housekeeping information in the reply */
9131         
9132         r_u->needed     = needed;
9133         r_u->returned   = num_entries;
9134
9135         if (needed > in_size) {
9136                 result = WERR_MORE_DATA;
9137                 goto done;
9138         }
9139                 
9140         /* copy data into the reply */
9141         
9142         r_u->ctr.size           = r_u->needed;
9143         r_u->ctr.size_of_array  = r_u->returned;
9144         r_u->ctr.values         = enum_values;
9145         
9146         
9147                 
9148 done:   
9149         if ( printer )
9150         free_a_printer(&printer, 2);
9151
9152         return result;
9153 }
9154
9155 /****************************************************************************
9156 ****************************************************************************/
9157
9158 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9159 {
9160         init_unistr(&info->name, name);
9161 }
9162
9163 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, 
9164                                                  UNISTR2 *environment, 
9165                                                  NEW_BUFFER *buffer, 
9166                                                  uint32 offered, 
9167                                                  uint32 *needed)
9168 {
9169         pstring path;
9170         pstring long_archi;
9171         PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9172
9173         unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9174
9175         if (!get_short_archi(long_archi))
9176                 return WERR_INVALID_ENVIRONMENT;
9177
9178         if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
9179                 return WERR_NOMEM;
9180
9181         pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9182
9183         fill_printprocessordirectory_1(info, path);
9184         
9185         *needed += spoolss_size_printprocessordirectory_info_1(info);
9186
9187         if (!alloc_buffer_size(buffer, *needed)) {
9188                 safe_free(info);
9189                 return WERR_INSUFFICIENT_BUFFER;
9190         }
9191
9192         smb_io_printprocessordirectory_1("", buffer, info, 0);
9193
9194         safe_free(info);
9195         
9196         if (*needed > offered)
9197                 return WERR_INSUFFICIENT_BUFFER;
9198         else
9199                 return WERR_OK;
9200 }
9201
9202 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9203 {
9204         uint32 level = q_u->level;
9205         NEW_BUFFER *buffer = NULL;
9206         uint32 offered = q_u->offered;
9207         uint32 *needed = &r_u->needed;
9208         WERROR result;
9209
9210         /* that's an [in out] buffer */
9211         spoolss_move_buffer(q_u->buffer, &r_u->buffer);
9212         buffer = r_u->buffer;
9213
9214         DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9215         
9216         *needed=0;
9217
9218         switch(level) {
9219         case 1:
9220                 result = getprintprocessordirectory_level_1
9221                   (&q_u->name, &q_u->environment, buffer, offered, needed);
9222                 break;
9223         default:
9224                 result = WERR_UNKNOWN_LEVEL;
9225         }
9226
9227         return result;
9228 }
9229
9230 #if 0
9231
9232 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u, 
9233                                  SPOOL_R_REPLYOPENPRINTER *r_u)
9234 {
9235         DEBUG(5,("_spoolss_replyopenprinter\n"));
9236
9237         DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9238
9239         return WERR_OK;
9240 }
9241
9242 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u, 
9243                                   SPOOL_R_REPLYCLOSEPRINTER *r_u)
9244 {
9245         DEBUG(5,("_spoolss_replycloseprinter\n"));
9246         return WERR_OK;
9247 }
9248
9249 #endif