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