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