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