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