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