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