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