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