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