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