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