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