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