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