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