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