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