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