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