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