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