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