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