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