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