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