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