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