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