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