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