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