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