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