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