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