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