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