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