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