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