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