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