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