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