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