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