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