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