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