1/*
2 *  Unix SMB/CIFS implementation.
3 *  RPC Pipe client / server routines
4 *  Copyright (C) Andrew Tridgell              1992-2000,
5 *  Copyright (C) Jean Fran�ois Micouleau      1998-2000.
6 *  Copyright (C) Gerald Carter                2002-2003.
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include "includes.h"
24
25extern DOM_SID global_sid_World;
26
27static TDB_CONTEXT *tdb_forms; /* used for forms files */
28static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29static TDB_CONTEXT *tdb_printers; /* used for printers files */
30
31#define FORMS_PREFIX "FORMS/"
32#define DRIVERS_PREFIX "DRIVERS/"
33#define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34#define PRINTERS_PREFIX "PRINTERS/"
35#define SECDESC_PREFIX "SECDESC/"
36#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37
38#define NTDRIVERS_DATABASE_VERSION_1 1
39#define NTDRIVERS_DATABASE_VERSION_2 2
40#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41
42#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
43
44/* Map generic permissions to printer object specific permissions */
45
46GENERIC_MAPPING printer_generic_mapping = {
47	PRINTER_READ,
48	PRINTER_WRITE,
49	PRINTER_EXECUTE,
50	PRINTER_ALL_ACCESS
51};
52
53STANDARD_MAPPING printer_std_mapping = {
54	PRINTER_READ,
55	PRINTER_WRITE,
56	PRINTER_EXECUTE,
57	PRINTER_ALL_ACCESS
58};
59
60/* Map generic permissions to print server object specific permissions */
61
62GENERIC_MAPPING printserver_generic_mapping = {
63	SERVER_READ,
64	SERVER_WRITE,
65	SERVER_EXECUTE,
66	SERVER_ALL_ACCESS
67};
68
69STANDARD_MAPPING printserver_std_mapping = {
70	SERVER_READ,
71	SERVER_WRITE,
72	SERVER_EXECUTE,
73	SERVER_ALL_ACCESS
74};
75
76/* We need one default form to support our default printer. Msoft adds the
77forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78array index). Letter is always first, so (for the current code) additions
79always put things in the correct order. */
80static const nt_forms_struct default_forms[] = {
81	{"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82	{"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83	{"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84	{"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85	{"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86	{"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87	{"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88	{"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89	{"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90	{"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91	{"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92	{"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93	{"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94	{"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95	{"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96	{"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97	{"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98	{"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99	{"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100	{"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101	{"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102	{"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103	{"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104	{"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105	{"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106	{"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107	{"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108	{"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109	{"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110	{"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111	{"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112	{"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113	{"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114	{"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115	{"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116	{"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117	{"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118	{"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119	{"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120	{"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121	{"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122	{"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123	{"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124	{"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125	{"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126	{"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127	{"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128	{"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129	{"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130	{"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131	{"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132	{"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133	{"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134	{"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135	{"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136	{"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137	{"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138	{"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139	{"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140	{"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141	{"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142	{"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143	{"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144	{"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145	{"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146	{"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147	{"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148	{"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149	{"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150	{"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151	{"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152	{"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153	{"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154	{"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155	{"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156	{"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157	{"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158	{"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159	{"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160	{"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161	{"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162	{"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163	{"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164	{"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165	{"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166	{"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167	{"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168	{"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169	{"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170	{"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171	{"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172	{"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173	{"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174	{"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175	{"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176	{"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177	{"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178	{"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179	{"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180	{"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181	{"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182	{"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183	{"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184	{"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185	{"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186	{"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187	{"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188	{"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189	{"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190	{"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191	{"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192	{"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193	{"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194	{"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195	{"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196	{"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197	{"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198	{"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
199};
200
201struct table_node {
202	const char 	*long_archi;
203	const char 	*short_archi;
204	int	version;
205};
206
207#define SPL_ARCH_WIN40		"WIN40"
208#define SPL_ARCH_W32X86		"W32X86"
209#define SPL_ARCH_W32MIPS	"W32MIPS"
210#define SPL_ARCH_W32ALPHA	"W32ALPHA"
211#define SPL_ARCH_W32PPC		"W32PPC"
212
213static const struct table_node archi_table[]= {
214
215	{"Windows 4.0",          SPL_ARCH_WIN40,	0 },
216	{"Windows NT x86",       SPL_ARCH_W32X86,	2 },
217	{"Windows NT R4000",     SPL_ARCH_W32MIPS,	2 },
218	{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,	2 },
219	{"Windows NT PowerPC",   SPL_ARCH_W32PPC,	2 },
220	{NULL,                   "",		-1 }
221};
222
223static BOOL upgrade_to_version_3(void)
224{
225	TDB_DATA kbuf, newkey, dbuf;
226
227	DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
228
229	for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230			newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
231
232		dbuf = tdb_fetch(tdb_drivers, kbuf);
233
234		if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235			DEBUG(0,("upgrade_to_version_3:moving form\n"));
236			if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237				SAFE_FREE(dbuf.dptr);
238				DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
239				return False;
240			}
241			if (tdb_delete(tdb_drivers, kbuf) != 0) {
242				SAFE_FREE(dbuf.dptr);
243				DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244				return False;
245			}
246		}
247
248		if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249			DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250			if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251				SAFE_FREE(dbuf.dptr);
252				DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
253				return False;
254			}
255			if (tdb_delete(tdb_drivers, kbuf) != 0) {
256				SAFE_FREE(dbuf.dptr);
257				DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
258				return False;
259			}
260		}
261
262		if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263			DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264			if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265				SAFE_FREE(dbuf.dptr);
266				DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
267				return False;
268			}
269			if (tdb_delete(tdb_drivers, kbuf) != 0) {
270				SAFE_FREE(dbuf.dptr);
271				DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
272				return False;
273			}
274		}
275
276		SAFE_FREE(dbuf.dptr);
277	}
278
279	return True;
280}
281
282/****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284****************************************************************************/
285
286BOOL nt_printing_init(void)
287{
288	static pid_t local_pid;
289	const char *vstring = "INFO/version";
290
291	if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
292		return True;
293
294	if (tdb_drivers)
295		tdb_close(tdb_drivers);
296	tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
297	if (!tdb_drivers) {
298		DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299			lock_path("ntdrivers.tdb"), strerror(errno) ));
300		return False;
301	}
302
303	if (tdb_printers)
304		tdb_close(tdb_printers);
305	tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
306	if (!tdb_printers) {
307		DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308			lock_path("ntprinters.tdb"), strerror(errno) ));
309		return False;
310	}
311
312	if (tdb_forms)
313		tdb_close(tdb_forms);
314	tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
315	if (!tdb_forms) {
316		DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317			lock_path("ntforms.tdb"), strerror(errno) ));
318		return False;
319	}
320
321	local_pid = sys_getpid();
322
323	/* handle a Samba upgrade */
324	tdb_lock_bystring(tdb_drivers, vstring, 0);
325	{
326		int32 vers_id;
327
328		/* Cope with byte-reversed older versions of the db. */
329		vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330		if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331			/* Written on a bigendian machine with old fetch_int code. Save as le. */
332			/* The only upgrade between V2 and V3 is to save the version in little-endian. */
333			tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334			vers_id = NTDRIVERS_DATABASE_VERSION;
335		}
336
337		if (vers_id != NTDRIVERS_DATABASE_VERSION) {
338
339			if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
340				if (!upgrade_to_version_3())
341					return False;
342			} else
343				tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
344
345			tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
346		}
347	}
348	tdb_unlock_bystring(tdb_drivers, vstring);
349
350	update_c_setprinter(True);
351
352	/*
353	 * register callback to handle updating printers as new
354	 * drivers are installed
355	 */
356
357	message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
358
359	/*
360	 * register callback to handle updating printer data
361	 * when a driver is initialized
362	 */
363
364	message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
365
366
367	return True;
368}
369
370/*******************************************************************
371 tdb traversal function for counting printers.
372********************************************************************/
373
374static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
375                                      TDB_DATA data, void *context)
376{
377	int *printer_count = (int*)context;
378
379	if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
380		(*printer_count)++;
381		DEBUG(10,("traverse_counting_printers: printer = [%s]  printer_count = %d\n", key.dptr, *printer_count));
382	}
383
384	return 0;
385}
386
387/*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392********************************************************************/
393
394uint32 update_c_setprinter(BOOL initialize)
395{
396	int32 c_setprinter;
397	int32 printer_count = 0;
398
399	tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
400
401	/* Traverse the tdb, counting the printers */
402	tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
403
404	/* If initializing, set c_setprinter to current printers count
405	 * otherwise, bump it by the current printer count
406	 */
407	if (!initialize)
408		c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
409	else
410		c_setprinter = printer_count;
411
412	DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
413	tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
414
415	tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
416
417	return (uint32)c_setprinter;
418}
419
420/*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422********************************************************************/
423
424uint32 get_c_setprinter(void)
425{
426	int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
427
428	if (c_setprinter == (int32)-1)
429		c_setprinter = update_c_setprinter(True);
430
431	DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
432
433	return (uint32)c_setprinter;
434}
435
436/****************************************************************************
437 Get builtin form struct list.
438****************************************************************************/
439
440int get_builtin_ntforms(nt_forms_struct **list)
441{
442	*list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
443	return sizeof(default_forms) / sizeof(default_forms[0]);
444}
445
446/****************************************************************************
447 get a builtin form struct
448****************************************************************************/
449
450BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
451{
452	int i,count;
453	fstring form_name;
454	unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
455	DEBUGADD(6,("Looking for builtin form %s \n", form_name));
456	count = sizeof(default_forms) / sizeof(default_forms[0]);
457	for (i=0;i<count;i++) {
458		if (strequal(form_name,default_forms[i].name)) {
459			DEBUGADD(6,("Found builtin form %s \n", form_name));
460			memcpy(form,&default_forms[i],sizeof(*form));
461			break;
462		}
463	}
464
465	return (i !=count);
466}
467
468/****************************************************************************
469get a form struct list
470****************************************************************************/
471int get_ntforms(nt_forms_struct **list)
472{
473	TDB_DATA kbuf, newkey, dbuf;
474	nt_forms_struct *tl;
475	nt_forms_struct form;
476	int ret;
477	int i;
478	int n = 0;
479
480	for (kbuf = tdb_firstkey(tdb_forms);
481	     kbuf.dptr;
482	     newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
483	{
484		if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
485			continue;
486
487		dbuf = tdb_fetch(tdb_forms, kbuf);
488		if (!dbuf.dptr)
489			continue;
490
491		fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
492		ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
493				 &i, &form.flag, &form.width, &form.length, &form.left,
494				 &form.top, &form.right, &form.bottom);
495		SAFE_FREE(dbuf.dptr);
496		if (ret != dbuf.dsize)
497			continue;
498
499		tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
500		if (!tl) {
501			DEBUG(0,("get_ntforms: Realloc fail.\n"));
502			return 0;
503		}
504		*list = tl;
505		(*list)[n] = form;
506		n++;
507	}
508
509
510	return n;
511}
512
513/****************************************************************************
514write a form struct list
515****************************************************************************/
516int write_ntforms(nt_forms_struct **list, int number)
517{
518	pstring buf, key;
519	int len;
520	TDB_DATA kbuf,dbuf;
521	int i;
522
523	for (i=0;i<number;i++) {
524		/* save index, so list is rebuilt in correct order */
525		len = tdb_pack(buf, sizeof(buf), "dddddddd",
526			       i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
527			       (*list)[i].left, (*list)[i].top, (*list)[i].right,
528			       (*list)[i].bottom);
529		if (len > sizeof(buf)) break;
530		slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
531		kbuf.dsize = strlen(key)+1;
532		kbuf.dptr = key;
533		dbuf.dsize = len;
534		dbuf.dptr = buf;
535		if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
536       }
537
538       return i;
539}
540
541/****************************************************************************
542add a form struct at the end of the list
543****************************************************************************/
544BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
545{
546	int n=0;
547	BOOL update;
548	fstring form_name;
549	nt_forms_struct *tl;
550
551	/*
552	 * NT tries to add forms even when
553	 * they are already in the base
554	 * only update the values if already present
555	 */
556
557	update=False;
558
559	unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
560	for (n=0; n<*count; n++) {
561		if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
562			DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
563			update=True;
564			break;
565		}
566	}
567
568	if (update==False) {
569		if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
570			DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
571			return False;
572		}
573		*list = tl;
574		unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
575		(*count)++;
576	}
577
578	(*list)[n].flag=form->flags;
579	(*list)[n].width=form->size_x;
580	(*list)[n].length=form->size_y;
581	(*list)[n].left=form->left;
582	(*list)[n].top=form->top;
583	(*list)[n].right=form->right;
584	(*list)[n].bottom=form->bottom;
585
586	return True;
587}
588
589/****************************************************************************
590 Delete a named form struct.
591****************************************************************************/
592
593BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
594{
595	pstring key;
596	TDB_DATA kbuf;
597	int n=0;
598	fstring form_name;
599
600	*ret = WERR_OK;
601
602	unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
603
604	for (n=0; n<*count; n++) {
605		if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
606			DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
607			break;
608		}
609	}
610
611	if (n == *count) {
612		DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
613		*ret = WERR_INVALID_PARAM;
614		return False;
615	}
616
617	slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
618	kbuf.dsize = strlen(key)+1;
619	kbuf.dptr = key;
620	if (tdb_delete(tdb_forms, kbuf) != 0) {
621		*ret = WERR_NOMEM;
622		return False;
623	}
624
625	return True;
626}
627
628/****************************************************************************
629 Update a form struct.
630****************************************************************************/
631
632void update_a_form(nt_forms_struct **list, const FORM *form, int count)
633{
634	int n=0;
635	fstring form_name;
636	unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
637
638	DEBUG(106, ("[%s]\n", form_name));
639	for (n=0; n<count; n++) {
640		DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
641		if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
642			break;
643	}
644
645	if (n==count) return;
646
647	(*list)[n].flag=form->flags;
648	(*list)[n].width=form->size_x;
649	(*list)[n].length=form->size_y;
650	(*list)[n].left=form->left;
651	(*list)[n].top=form->top;
652	(*list)[n].right=form->right;
653	(*list)[n].bottom=form->bottom;
654}
655
656/****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659****************************************************************************/
660int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
661{
662	int total=0;
663	const char *short_archi;
664	fstring *fl;
665	pstring key;
666	TDB_DATA kbuf, newkey;
667
668	short_archi = get_short_archi(architecture);
669	slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
670
671	for (kbuf = tdb_firstkey(tdb_drivers);
672	     kbuf.dptr;
673	     newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
674
675		if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
676			continue;
677
678		if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
679			DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
680			return -1;
681		}
682		else *list = fl;
683
684		fstrcpy((*list)[total], kbuf.dptr+strlen(key));
685		total++;
686	}
687
688	return(total);
689}
690
691/****************************************************************************
692function to do the mapping between the long architecture name and
693the short one.
694****************************************************************************/
695const char *get_short_archi(const char *long_archi)
696{
697        int i=-1;
698
699        DEBUG(107,("Getting architecture dependant directory\n"));
700        do {
701                i++;
702        } while ( (archi_table[i].long_archi!=NULL ) &&
703                  StrCaseCmp(long_archi, archi_table[i].long_archi) );
704
705        if (archi_table[i].long_archi==NULL) {
706                DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
707                return NULL;
708        }
709
710	/* this might be client code - but shouldn't this be an fstrcpy etc? */
711
712
713        DEBUGADD(108,("index: [%d]\n", i));
714        DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
715        DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
716
717	return archi_table[i].short_archi;
718}
719
720/****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726****************************************************************************/
727
728static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
729{
730	int     i;
731	char    *buf = NULL;
732	ssize_t byte_count;
733
734	if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735		DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736				fname, PE_HEADER_SIZE));
737		goto error_exit;
738	}
739
740	/* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741	if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742		DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
743			 fname, (unsigned long)byte_count));
744		goto no_version_info;
745	}
746
747	/* Is this really a DOS header? */
748	if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749		DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750				fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751		goto no_version_info;
752	}
753
754	/* Skip OEM header (if any) and the DOS stub to start of Windows header */
755	if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756		DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
757				fname, errno));
758		/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759		goto no_version_info;
760	}
761
762	if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763		DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
764			 fname, (unsigned long)byte_count));
765		/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766		goto no_version_info;
767	}
768
769	/* The header may be a PE (Portable Executable) or an NE (New Executable) */
770	if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
771		unsigned int num_sections;
772		unsigned int section_table_bytes;
773
774		if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775			DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776					fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777			/* At this point, we assume the file is in error. It still could be somthing
778			 * else besides a PE file, but it unlikely at this point.
779			 */
780			goto error_exit;
781		}
782
783		/* get the section table */
784		num_sections        = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785		section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
786		if (section_table_bytes == 0)
787			goto error_exit;
788
789		SAFE_FREE(buf);
790		if ((buf=malloc(section_table_bytes)) == NULL) {
791			DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
792					fname, section_table_bytes));
793			goto error_exit;
794		}
795
796		if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
797			DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
798				 fname, (unsigned long)byte_count));
799			goto error_exit;
800		}
801
802		/* Iterate the section table looking for the resource section ".rsrc" */
803		for (i = 0; i < num_sections; i++) {
804			int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
805
806			if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
807				unsigned int section_pos   = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
808				unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
809
810				if (section_bytes == 0)
811					goto error_exit;
812
813				SAFE_FREE(buf);
814				if ((buf=malloc(section_bytes)) == NULL) {
815					DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
816							fname, section_bytes));
817					goto error_exit;
818				}
819
820				/* Seek to the start of the .rsrc section info */
821				if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
822					DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
823							fname, errno));
824					goto error_exit;
825				}
826
827				if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
828					DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
829						 fname, (unsigned long)byte_count));
830					goto error_exit;
831				}
832
833				if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
834					goto error_exit;
835
836				for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
837					/* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
838					if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
839						/* Align to next long address */
840						int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
841
842						if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
843							*major = IVAL(buf,pos+VS_MAJOR_OFFSET);
844							*minor = IVAL(buf,pos+VS_MINOR_OFFSET);
845
846							DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
847									  fname, *major, *minor,
848									  (*major>>16)&0xffff, *major&0xffff,
849									  (*minor>>16)&0xffff, *minor&0xffff));
850							SAFE_FREE(buf);
851							return 1;
852						}
853					}
854				}
855			}
856		}
857
858		/* Version info not found, fall back to origin date/time */
859		DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
860		SAFE_FREE(buf);
861		return 0;
862
863	} else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
864		if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
865			DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
866					fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
867			/* At this point, we assume the file is in error. It still could be somthing
868			 * else besides a NE file, but it unlikely at this point. */
869			goto error_exit;
870		}
871
872		/* Allocate a bit more space to speed up things */
873		SAFE_FREE(buf);
874		if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
875			DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes  = %d\n",
876					fname, PE_HEADER_SIZE));
877			goto error_exit;
878		}
879
880		/* This is a HACK! I got tired of trying to sort through the messy
881		 * 'NE' file format. If anyone wants to clean this up please have at
882		 * it, but this works. 'NE' files will eventually fade away. JRR */
883		while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
884			/* Cover case that should not occur in a well formed 'NE' .dll file */
885			if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
886
887			for(i=0; i<byte_count; i++) {
888				/* Fast skip past data that can't possibly match */
889				if (buf[i] != 'V') continue;
890
891				/* Potential match data crosses buf boundry, move it to beginning
892				 * of buf, and fill the buf with as much as it will hold. */
893				if (i>byte_count-VS_VERSION_INFO_SIZE) {
894					int bc;
895
896					memcpy(buf, &buf[i], byte_count-i);
897					if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
898								   (byte_count-i))) < 0) {
899
900						DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
901								 fname, errno));
902						goto error_exit;
903					}
904
905					byte_count = bc + (byte_count - i);
906					if (byte_count<VS_VERSION_INFO_SIZE) break;
907
908					i = 0;
909				}
910
911				/* Check that the full signature string and the magic number that
912				 * follows exist (not a perfect solution, but the chances that this
913				 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
914				 * twice, as it is simpler to read the code. */
915				if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
916					/* Compute skip alignment to next long address */
917					int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
918								 sizeof(VS_SIGNATURE)) & 3;
919					if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
920
921					*major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
922					*minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
923					DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
924							  fname, *major, *minor,
925							  (*major>>16)&0xffff, *major&0xffff,
926							  (*minor>>16)&0xffff, *minor&0xffff));
927					SAFE_FREE(buf);
928					return 1;
929				}
930			}
931		}
932
933		/* Version info not found, fall back to origin date/time */
934		DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
935		SAFE_FREE(buf);
936		return 0;
937
938	} else
939		/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
940		DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
941				fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
942
943	no_version_info:
944		SAFE_FREE(buf);
945		return 0;
946
947	error_exit:
948		SAFE_FREE(buf);
949		return -1;
950}
951
952/****************************************************************************
953Drivers for Microsoft systems contain multiple files. Often, multiple drivers
954share one or more files. During the MS installation process files are checked
955to insure that only a newer version of a shared file is installed over an
956older version. There are several possibilities for this comparison. If there
957is no previous version, the new one is newer (obviously). If either file is
958missing the version info structure, compare the creation date (on Unix use
959the modification date). Otherwise chose the numerically larger version number.
960****************************************************************************/
961
962static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
963{
964	BOOL   use_version = True;
965	pstring filepath;
966
967	uint32 new_major;
968	uint32 new_minor;
969	time_t new_create_time;
970
971	uint32 old_major;
972	uint32 old_minor;
973	time_t old_create_time;
974
975	int access_mode;
976	int action;
977	files_struct    *fsp = NULL;
978	SMB_STRUCT_STAT st;
979	SMB_STRUCT_STAT stat_buf;
980	BOOL bad_path;
981
982	ZERO_STRUCT(st);
983	ZERO_STRUCT(stat_buf);
984	new_create_time = (time_t)0;
985	old_create_time = (time_t)0;
986
987	/* Get file version info (if available) for previous file (if it exists) */
988	pstrcpy(filepath, old_file);
989
990	unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
991
992	fsp = open_file_shared(conn, filepath, &stat_buf,
993						   SET_OPEN_MODE(DOS_OPEN_RDONLY),
994						   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
995						   0, 0, &access_mode, &action);
996	if (!fsp) {
997		/* Old file not found, so by definition new file is in fact newer */
998		DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
999				filepath, errno));
1000		return True;
1001
1002	} else {
1003		int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1004		if (ret == -1) goto error_exit;
1005
1006		if (!ret) {
1007			DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1008					 old_file));
1009			use_version = False;
1010			if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1011			old_create_time = st.st_mtime;
1012			DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1013		}
1014	}
1015	close_file(fsp, True);
1016
1017	/* Get file version info (if available) for new file */
1018	pstrcpy(filepath, new_file);
1019	unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1020
1021	fsp = open_file_shared(conn, filepath, &stat_buf,
1022						   SET_OPEN_MODE(DOS_OPEN_RDONLY),
1023						   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1024						   0, 0, &access_mode, &action);
1025	if (!fsp) {
1026		/* New file not found, this shouldn't occur if the caller did its job */
1027		DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1028				filepath, errno));
1029		goto error_exit;
1030
1031	} else {
1032		int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1033		if (ret == -1) goto error_exit;
1034
1035		if (!ret) {
1036			DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1037					 new_file));
1038			use_version = False;
1039			if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1040			new_create_time = st.st_mtime;
1041			DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1042		}
1043	}
1044	close_file(fsp, True);
1045
1046	if (use_version && (new_major != old_major || new_minor != old_minor)) {
1047		/* Compare versions and choose the larger version number */
1048		if (new_major > old_major ||
1049			(new_major == old_major && new_minor > old_minor)) {
1050
1051			DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1052			return True;
1053		}
1054		else {
1055			DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1056			return False;
1057		}
1058
1059	} else {
1060		/* Compare modification time/dates and choose the newest time/date */
1061		if (new_create_time > old_create_time) {
1062			DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1063			return True;
1064		}
1065		else {
1066			DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1067			return False;
1068		}
1069	}
1070
1071	error_exit:
1072		if(fsp)
1073			close_file(fsp, True);
1074		return -1;
1075}
1076
1077/****************************************************************************
1078Determine the correct cVersion associated with an architecture and driver
1079****************************************************************************/
1080static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1081				   struct current_user *user, WERROR *perr)
1082{
1083	int               cversion;
1084	int               access_mode;
1085	int               action;
1086	NTSTATUS          nt_status;
1087 	pstring           driverpath;
1088	DATA_BLOB         null_pw;
1089	fstring           res_type;
1090	files_struct      *fsp = NULL;
1091	BOOL              bad_path;
1092	SMB_STRUCT_STAT   st;
1093	connection_struct *conn;
1094
1095	ZERO_STRUCT(st);
1096
1097	*perr = WERR_INVALID_PARAM;
1098
1099	/* If architecture is Windows 95/98/ME, the version is always 0. */
1100	if (strcmp(architecture, "WIN40") == 0) {
1101		DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1102		*perr = WERR_OK;
1103		return 0;
1104	}
1105
1106	/*
1107	 * Connect to the print$ share under the same account as the user connected
1108	 * to the rpc pipe. Note we must still be root to do this.
1109	 */
1110
1111	/* Null password is ok - we are already an authenticated user... */
1112	null_pw = data_blob(NULL, 0);
1113	fstrcpy(res_type, "A:");
1114 	become_root();
1115	conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1116	unbecome_root();
1117
1118	if (conn == NULL) {
1119		DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1120		*perr = ntstatus_to_werror(nt_status);
1121		return -1;
1122	}
1123
1124	/* We are temporarily becoming the connection user. */
1125	if (!become_user(conn, user->vuid)) {
1126		DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1127		*perr = WERR_ACCESS_DENIED;
1128		return -1;
1129	}
1130
1131	/* Open the driver file (Portable Executable format) and determine the
1132	 * deriver the cversion. */
1133	slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1134
1135	unix_convert(driverpath,conn,NULL,&bad_path,&st);
1136
1137	fsp = open_file_shared(conn, driverpath, &st,
1138						   SET_OPEN_MODE(DOS_OPEN_RDONLY),
1139						   (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1140						   0, 0, &access_mode, &action);
1141	if (!fsp) {
1142		DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1143				driverpath, errno));
1144		*perr = WERR_ACCESS_DENIED;
1145		goto error_exit;
1146	}
1147	else {
1148		uint32 major;
1149		uint32 minor;
1150		int    ret = get_file_version(fsp, driverpath, &major, &minor);
1151		if (ret == -1) goto error_exit;
1152
1153		if (!ret) {
1154			DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1155			goto error_exit;
1156		}
1157
1158		/*
1159		 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1160		 * for more details. Version in this case is not just the version of the
1161		 * file, but the version in the sense of kernal mode (2) vs. user mode
1162		 * (3) drivers. Other bits of the version fields are the version info.
1163		 * JRR 010716
1164		*/
1165		cversion = major & 0x0000ffff;
1166		switch (cversion) {
1167			case 2: /* WinNT drivers */
1168			case 3: /* Win2K drivers */
1169				break;
1170
1171			default:
1172				DEBUG(6,("get_correct_cversion: cversion invalid [%s]  cversion = %d\n",
1173					driverpath, cversion));
1174				goto error_exit;
1175		}
1176
1177		DEBUG(10,("get_correct_cversion: Version info found [%s]  major = 0x%x  minor = 0x%x\n",
1178				  driverpath, major, minor));
1179	}
1180
1181    DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1182			driverpath, cversion));
1183
1184	close_file(fsp, True);
1185	close_cnum(conn, user->vuid);
1186	unbecome_user();
1187	*perr = WERR_OK;
1188	return cversion;
1189
1190
1191  error_exit:
1192
1193	if(fsp)
1194		close_file(fsp, True);
1195
1196	close_cnum(conn, user->vuid);
1197	unbecome_user();
1198	return -1;
1199}
1200
1201/****************************************************************************
1202****************************************************************************/
1203static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1204											 struct current_user *user)
1205{
1206	const char *architecture;
1207	fstring new_name;
1208	char *p;
1209	int i;
1210	WERROR err;
1211
1212	/* clean up the driver name.
1213	 * we can get .\driver.dll
1214	 * or worse c:\windows\system\driver.dll !
1215	 */
1216	/* using an intermediate string to not have overlaping memcpy()'s */
1217	if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1218		fstrcpy(new_name, p+1);
1219		fstrcpy(driver->driverpath, new_name);
1220	}
1221
1222	if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1223		fstrcpy(new_name, p+1);
1224		fstrcpy(driver->datafile, new_name);
1225	}
1226
1227	if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1228		fstrcpy(new_name, p+1);
1229		fstrcpy(driver->configfile, new_name);
1230	}
1231
1232	if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1233		fstrcpy(new_name, p+1);
1234		fstrcpy(driver->helpfile, new_name);
1235	}
1236
1237	if (driver->dependentfiles) {
1238		for (i=0; *driver->dependentfiles[i]; i++) {
1239			if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1240				fstrcpy(new_name, p+1);
1241				fstrcpy(driver->dependentfiles[i], new_name);
1242			}
1243		}
1244	}
1245
1246	architecture = get_short_archi(driver->environment);
1247
1248	/* jfm:7/16/2000 the client always sends the cversion=0.
1249	 * The server should check which version the driver is by reading
1250	 * the PE header of driver->driverpath.
1251	 *
1252	 * For Windows 95/98 the version is 0 (so the value sent is correct)
1253	 * For Windows NT (the architecture doesn't matter)
1254	 *	NT 3.1: cversion=0
1255	 *	NT 3.5/3.51: cversion=1
1256	 *	NT 4: cversion=2
1257	 *	NT2K: cversion=3
1258	 */
1259	if ((driver->cversion = get_correct_cversion( architecture,
1260									driver->driverpath, user, &err)) == -1)
1261		return err;
1262
1263	return WERR_OK;
1264}
1265
1266/****************************************************************************
1267****************************************************************************/
1268static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1269{
1270	const char *architecture;
1271	fstring new_name;
1272	char *p;
1273	int i;
1274	WERROR err;
1275
1276	/* clean up the driver name.
1277	 * we can get .\driver.dll
1278	 * or worse c:\windows\system\driver.dll !
1279	 */
1280	/* using an intermediate string to not have overlaping memcpy()'s */
1281	if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1282		fstrcpy(new_name, p+1);
1283		fstrcpy(driver->driverpath, new_name);
1284	}
1285
1286	if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1287		fstrcpy(new_name, p+1);
1288		fstrcpy(driver->datafile, new_name);
1289	}
1290
1291	if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1292		fstrcpy(new_name, p+1);
1293		fstrcpy(driver->configfile, new_name);
1294	}
1295
1296	if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1297		fstrcpy(new_name, p+1);
1298		fstrcpy(driver->helpfile, new_name);
1299	}
1300
1301	if (driver->dependentfiles) {
1302		for (i=0; *driver->dependentfiles[i]; i++) {
1303			if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1304				fstrcpy(new_name, p+1);
1305				fstrcpy(driver->dependentfiles[i], new_name);
1306			}
1307		}
1308	}
1309
1310	architecture = get_short_archi(driver->environment);
1311
1312	/* jfm:7/16/2000 the client always sends the cversion=0.
1313	 * The server should check which version the driver is by reading
1314	 * the PE header of driver->driverpath.
1315	 *
1316	 * For Windows 95/98 the version is 0 (so the value sent is correct)
1317	 * For Windows NT (the architecture doesn't matter)
1318	 *	NT 3.1: cversion=0
1319	 *	NT 3.5/3.51: cversion=1
1320	 *	NT 4: cversion=2
1321	 *	NT2K: cversion=3
1322	 */
1323	if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1324		return err;
1325
1326	return WERR_OK;
1327}
1328
1329/****************************************************************************
1330****************************************************************************/
1331WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1332							  uint32 level, struct current_user *user)
1333{
1334	switch (level) {
1335		case 3:
1336		{
1337			NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1338			driver=driver_abstract.info_3;
1339			return clean_up_driver_struct_level_3(driver, user);
1340		}
1341		case 6:
1342		{
1343			NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1344			driver=driver_abstract.info_6;
1345			return clean_up_driver_struct_level_6(driver, user);
1346		}
1347		default:
1348			return WERR_INVALID_PARAM;
1349	}
1350}
1351
1352/****************************************************************************
1353 This function sucks and should be replaced. JRA.
1354****************************************************************************/
1355
1356static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1357{
1358    dst->cversion  = src->version;
1359
1360    fstrcpy( dst->name, src->name);
1361    fstrcpy( dst->environment, src->environment);
1362    fstrcpy( dst->driverpath, src->driverpath);
1363    fstrcpy( dst->datafile, src->datafile);
1364    fstrcpy( dst->configfile, src->configfile);
1365    fstrcpy( dst->helpfile, src->helpfile);
1366    fstrcpy( dst->monitorname, src->monitorname);
1367    fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1368    dst->dependentfiles = src->dependentfiles;
1369}
1370
1371#if 0 /* Debugging function */
1372
1373static char* ffmt(unsigned char *c){
1374	int i;
1375	static char ffmt_str[17];
1376
1377	for (i=0; i<16; i++) {
1378		if ((c[i] < ' ') || (c[i] > '~'))
1379			ffmt_str[i]='.';
1380		else
1381			ffmt_str[i]=c[i];
1382	}
1383    ffmt_str[16]='\0';
1384	return ffmt_str;
1385}
1386
1387#endif
1388
1389/****************************************************************************
1390****************************************************************************/
1391BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1392				  struct current_user *user, WERROR *perr)
1393{
1394	NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1395	NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1396	const char *architecture;
1397	pstring new_dir;
1398	pstring old_name;
1399	pstring new_name;
1400	DATA_BLOB null_pw;
1401	connection_struct *conn;
1402	NTSTATUS nt_status;
1403	pstring inbuf;
1404	pstring outbuf;
1405	fstring res_type;
1406	int ver = 0;
1407	int i;
1408
1409	memset(inbuf, '\0', sizeof(inbuf));
1410	memset(outbuf, '\0', sizeof(outbuf));
1411	*perr = WERR_OK;
1412
1413	if (level==3)
1414		driver=driver_abstract.info_3;
1415	else if (level==6) {
1416		convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1417		driver = &converted_driver;
1418	} else {
1419		DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1420		return False;
1421	}
1422
1423	architecture = get_short_archi(driver->environment);
1424
1425	/*
1426	 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1427	 * Note we must be root to do this.
1428	 */
1429
1430	null_pw = data_blob(NULL, 0);
1431	fstrcpy(res_type, "A:");
1432	become_root();
1433	conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1434	unbecome_root();
1435
1436	if (conn == NULL) {
1437		DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1438		*perr = ntstatus_to_werror(nt_status);
1439		return False;
1440	}
1441
1442	/*
1443	 * Save who we are - we are temporarily becoming the connection user.
1444	 */
1445
1446	if (!become_user(conn, conn->vuid)) {
1447		DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1448		return False;
1449	}
1450
1451	/*
1452	 * make the directories version and version\driver_name
1453	 * under the architecture directory.
1454	 */
1455	DEBUG(5,("Creating first directory\n"));
1456	slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1457	mkdir_internal(conn, new_dir);
1458
1459	/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1460	 * listed for this driver which has already been moved, skip it (note:
1461	 * drivers may list the same file name several times. Then check if the
1462	 * file already exists in archi\cversion\, if so, check that the version
1463	 * info (or time stamps if version info is unavailable) is newer (or the
1464	 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1465	 * Otherwise, delete the file.
1466	 *
1467	 * If a file is not moved to archi\cversion\ because of an error, all the
1468	 * rest of the 'unmoved' driver files are removed from archi\. If one or
1469	 * more of the driver's files was already moved to archi\cversion\, it
1470	 * potentially leaves the driver in a partially updated state. Version
1471	 * trauma will most likely occur if an client attempts to use any printer
1472	 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1473	 * done is appropriate... later JRR
1474	 */
1475
1476	DEBUG(5,("Moving files now !\n"));
1477
1478	if (driver->driverpath && strlen(driver->driverpath)) {
1479		slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1480		slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1481		if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1482			NTSTATUS status;
1483			status = rename_internals(conn, new_name, old_name, True);
1484			if (!NT_STATUS_IS_OK(status)) {
1485				DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1486						new_name, old_name));
1487				*perr = ntstatus_to_werror(status);
1488				unlink_internals(conn, 0, new_name);
1489				ver = -1;
1490			}
1491		}
1492		else
1493			unlink_internals(conn, 0, new_name);
1494	}
1495
1496	if (driver->datafile && strlen(driver->datafile)) {
1497		if (!strequal(driver->datafile, driver->driverpath)) {
1498			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1499			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1500			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1501				NTSTATUS status;
1502				status = rename_internals(conn, new_name, old_name, True);
1503				if (!NT_STATUS_IS_OK(status)) {
1504					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1505							new_name, old_name));
1506					*perr = ntstatus_to_werror(status);
1507					unlink_internals(conn, 0, new_name);
1508					ver = -1;
1509				}
1510			}
1511			else
1512				unlink_internals(conn, 0, new_name);
1513		}
1514	}
1515
1516	if (driver->configfile && strlen(driver->configfile)) {
1517		if (!strequal(driver->configfile, driver->driverpath) &&
1518			!strequal(driver->configfile, driver->datafile)) {
1519			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1520			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1521			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1522				NTSTATUS status;
1523				status = rename_internals(conn, new_name, old_name, True);
1524				if (!NT_STATUS_IS_OK(status)) {
1525					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1526							new_name, old_name));
1527					*perr = ntstatus_to_werror(status);
1528					unlink_internals(conn, 0, new_name);
1529					ver = -1;
1530				}
1531			}
1532			else
1533				unlink_internals(conn, 0, new_name);
1534		}
1535	}
1536
1537	if (driver->helpfile && strlen(driver->helpfile)) {
1538		if (!strequal(driver->helpfile, driver->driverpath) &&
1539			!strequal(driver->helpfile, driver->datafile) &&
1540			!strequal(driver->helpfile, driver->configfile)) {
1541			slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1542			slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1543			if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1544				NTSTATUS status;
1545				status = rename_internals(conn, new_name, old_name, True);
1546				if (!NT_STATUS_IS_OK(status)) {
1547					DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1548							new_name, old_name));
1549					*perr = ntstatus_to_werror(status);
1550					unlink_internals(conn, 0, new_name);
1551					ver = -1;
1552				}
1553			}
1554			else
1555				unlink_internals(conn, 0, new_name);
1556		}
1557	}
1558
1559	if (driver->dependentfiles) {
1560		for (i=0; *driver->dependentfiles[i]; i++) {
1561			if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1562				!strequal(driver->dependentfiles[i], driver->datafile) &&
1563				!strequal(driver->dependentfiles[i], driver->configfile) &&
1564				!strequal(driver->dependentfiles[i], driver->helpfile)) {
1565				int j;
1566				for (j=0; j < i; j++) {
1567					if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1568						goto NextDriver;
1569					}
1570				}
1571
1572				slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1573				slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1574				if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1575					NTSTATUS status;
1576					status = rename_internals(conn, new_name, old_name, True);
1577					if (!NT_STATUS_IS_OK(status)) {
1578						DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1579								new_name, old_name));
1580						*perr = ntstatus_to_werror(status);
1581						unlink_internals(conn, 0, new_name);
1582						ver = -1;
1583					}
1584				}
1585				else
1586					unlink_internals(conn, 0, new_name);
1587			}
1588		NextDriver: ;
1589		}
1590	}
1591
1592	close_cnum(conn, user->vuid);
1593	unbecome_user();
1594
1595	return ver == -1 ? False : True;
1596}
1597
1598/****************************************************************************
1599****************************************************************************/
1600static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1601{
1602	int len, buflen;
1603	const char *architecture;
1604	pstring directory;
1605	fstring temp_name;
1606	pstring key;
1607	char *buf;
1608	int i, ret;
1609	TDB_DATA kbuf, dbuf;
1610
1611	architecture = get_short_archi(driver->environment);
1612
1613	/* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1614	 * \\server is added in the rpc server layer.
1615	 * It does make sense to NOT store the server's name in the printer TDB.
1616	 */
1617
1618	slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1619
1620	/* .inf files do not always list a file for each of the four standard files.
1621	 * Don't prepend a path to a null filename, or client claims:
1622	 *   "The server on which the printer resides does not have a suitable
1623	 *   <printer driver name> printer driver installed. Click OK if you
1624	 *   wish to install the driver on your local machine."
1625	 */
1626	if (strlen(driver->driverpath)) {
1627		fstrcpy(temp_name, driver->driverpath);
1628		slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1629	}
1630
1631	if (strlen(driver->datafile)) {
1632		fstrcpy(temp_name, driver->datafile);
1633		slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1634	}
1635
1636	if (strlen(driver->configfile)) {
1637		fstrcpy(temp_name, driver->configfile);
1638		slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1639	}
1640
1641	if (strlen(driver->helpfile)) {
1642		fstrcpy(temp_name, driver->helpfile);
1643		slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1644	}
1645
1646	if (driver->dependentfiles) {
1647		for (i=0; *driver->dependentfiles[i]; i++) {
1648			fstrcpy(temp_name, driver->dependentfiles[i]);
1649			slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1650		}
1651	}
1652
1653	slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1654
1655	DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1656
1657	buf = NULL;
1658	len = buflen = 0;
1659
1660 again:
1661	len = 0;
1662	len += tdb_pack(buf+len, buflen-len, "dffffffff",
1663			driver->cversion,
1664			driver->name,
1665			driver->environment,
1666			driver->driverpath,
1667			driver->datafile,
1668			driver->configfile,
1669			driver->helpfile,
1670			driver->monitorname,
1671			driver->defaultdatatype);
1672
1673	if (driver->dependentfiles) {
1674		for (i=0; *driver->dependentfiles[i]; i++) {
1675			len += tdb_pack(buf+len, buflen-len, "f",
1676					driver->dependentfiles[i]);
1677		}
1678	}
1679
1680	if (len != buflen) {
1681		char *tb;
1682
1683		tb = (char *)Realloc(buf, len);
1684		if (!tb) {
1685			DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1686			ret = -1;
1687			goto done;
1688		}
1689		else buf = tb;
1690		buflen = len;
1691		goto again;
1692	}
1693
1694
1695	kbuf.dptr = key;
1696	kbuf.dsize = strlen(key)+1;
1697	dbuf.dptr = buf;
1698	dbuf.dsize = len;
1699
1700	ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1701
1702done:
1703	if (ret)
1704		DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1705
1706	SAFE_FREE(buf);
1707	return ret;
1708}
1709
1710/****************************************************************************
1711****************************************************************************/
1712static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1713{
1714	NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1715
1716	ZERO_STRUCT(info3);
1717	info3.cversion = driver->version;
1718	fstrcpy(info3.name,driver->name);
1719	fstrcpy(info3.environment,driver->environment);
1720	fstrcpy(info3.driverpath,driver->driverpath);
1721	fstrcpy(info3.datafile,driver->datafile);
1722	fstrcpy(info3.configfile,driver->configfile);
1723	fstrcpy(info3.helpfile,driver->helpfile);
1724	fstrcpy(info3.monitorname,driver->monitorname);
1725	fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1726	info3.dependentfiles = driver->dependentfiles;
1727
1728	return add_a_printer_driver_3(&info3);
1729}
1730
1731
1732/****************************************************************************
1733****************************************************************************/
1734static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1735{
1736	NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1737
1738	ZERO_STRUCT(info);
1739
1740	fstrcpy(info.name, driver);
1741	fstrcpy(info.defaultdatatype, "RAW");
1742
1743	fstrcpy(info.driverpath, "");
1744	fstrcpy(info.datafile, "");
1745	fstrcpy(info.configfile, "");
1746	fstrcpy(info.helpfile, "");
1747
1748	if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1749		return WERR_NOMEM;
1750
1751	memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1752	fstrcpy(info.dependentfiles[0], "");
1753
1754	*info_ptr = memdup(&info, sizeof(info));
1755
1756	return WERR_OK;
1757}
1758
1759/****************************************************************************
1760****************************************************************************/
1761static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1762{
1763	NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1764	TDB_DATA kbuf, dbuf;
1765	const char *architecture;
1766	int len = 0;
1767	int i;
1768	pstring key;
1769
1770	ZERO_STRUCT(driver);
1771
1772	architecture = get_short_archi(arch);
1773
1774	/* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1775
1776	if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1777		version = 0;
1778
1779	DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1780
1781	slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1782
1783	kbuf.dptr = key;
1784	kbuf.dsize = strlen(key)+1;
1785
1786	dbuf = tdb_fetch(tdb_drivers, kbuf);
1787	if (!dbuf.dptr)
1788		return WERR_UNKNOWN_PRINTER_DRIVER;
1789
1790	len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1791			  &driver.cversion,
1792			  driver.name,
1793			  driver.environment,
1794			  driver.driverpath,
1795			  driver.datafile,
1796			  driver.configfile,
1797			  driver.helpfile,
1798			  driver.monitorname,
1799			  driver.defaultdatatype);
1800
1801	i=0;
1802	while (len < dbuf.dsize) {
1803		fstring *tddfs;
1804
1805		tddfs = (fstring *)Realloc(driver.dependentfiles,
1806							 sizeof(fstring)*(i+2));
1807		if (tddfs == NULL) {
1808			DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1809			break;
1810		}
1811		else driver.dependentfiles = tddfs;
1812
1813		len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1814				  &driver.dependentfiles[i]);
1815		i++;
1816	}
1817
1818	if (driver.dependentfiles != NULL)
1819		fstrcpy(driver.dependentfiles[i], "");
1820
1821	SAFE_FREE(dbuf.dptr);
1822
1823	if (len != dbuf.dsize) {
1824		SAFE_FREE(driver.dependentfiles);
1825
1826		return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1827	}
1828
1829	*info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1830
1831	return WERR_OK;
1832}
1833
1834/****************************************************************************
1835 Debugging function, dump at level 6 the struct in the logs.
1836****************************************************************************/
1837
1838static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1839{
1840	uint32 result;
1841	NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1842	int i;
1843
1844	DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1845
1846	switch (level)
1847	{
1848		case 3:
1849		{
1850			if (driver.info_3 == NULL)
1851				result=5;
1852			else {
1853				info3=driver.info_3;
1854
1855				DEBUGADD(20,("version:[%d]\n",         info3->cversion));
1856				DEBUGADD(20,("name:[%s]\n",            info3->name));
1857				DEBUGADD(20,("environment:[%s]\n",     info3->environment));
1858				DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
1859				DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
1860				DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
1861				DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
1862				DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
1863				DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1864
1865				for (i=0; info3->dependentfiles &&
1866					  *info3->dependentfiles[i]; i++) {
1867					DEBUGADD(20,("dependentfile:[%s]\n",
1868						      info3->dependentfiles[i]));
1869				}
1870				result=0;
1871			}
1872			break;
1873		}
1874		default:
1875			DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1876			result=1;
1877			break;
1878	}
1879
1880	return result;
1881}
1882
1883/****************************************************************************
1884****************************************************************************/
1885int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1886{
1887	int len = 0;
1888
1889	len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1890
1891	if (!nt_devmode)
1892		return len;
1893
1894	len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1895			nt_devmode->devicename,
1896			nt_devmode->formname,
1897
1898			nt_devmode->specversion,
1899			nt_devmode->driverversion,
1900			nt_devmode->size,
1901			nt_devmode->driverextra,
1902			nt_devmode->orientation,
1903			nt_devmode->papersize,
1904			nt_devmode->paperlength,
1905			nt_devmode->paperwidth,
1906			nt_devmode->scale,
1907			nt_devmode->copies,
1908			nt_devmode->defaultsource,
1909			nt_devmode->printquality,
1910			nt_devmode->color,
1911			nt_devmode->duplex,
1912			nt_devmode->yresolution,
1913			nt_devmode->ttoption,
1914			nt_devmode->collate,
1915			nt_devmode->logpixels,
1916
1917			nt_devmode->fields,
1918			nt_devmode->bitsperpel,
1919			nt_devmode->pelswidth,
1920			nt_devmode->pelsheight,
1921			nt_devmode->displayflags,
1922			nt_devmode->displayfrequency,
1923			nt_devmode->icmmethod,
1924			nt_devmode->icmintent,
1925			nt_devmode->mediatype,
1926			nt_devmode->dithertype,
1927			nt_devmode->reserved1,
1928			nt_devmode->reserved2,
1929			nt_devmode->panningwidth,
1930			nt_devmode->panningheight,
1931			nt_devmode->private);
1932
1933
1934	if (nt_devmode->private) {
1935		len += tdb_pack(buf+len, buflen-len, "B",
1936				nt_devmode->driverextra,
1937				nt_devmode->private);
1938	}
1939
1940	DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1941
1942	return len;
1943}
1944
1945/****************************************************************************
1946 Pack all values in all printer keys
1947 ***************************************************************************/
1948
1949static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1950{
1951	int 		len = 0;
1952	int 		i, j;
1953	REGISTRY_VALUE	*val;
1954	REGVAL_CTR	*val_ctr;
1955	pstring		path;
1956	int		num_values;
1957
1958	if ( !data )
1959		return 0;
1960
1961	/* loop over all keys */
1962
1963	for ( i=0; i<data->num_keys; i++ ) {
1964		val_ctr = &data->keys[i].values;
1965		num_values = regval_ctr_numvals( val_ctr );
1966
1967		/* loop over all values */
1968
1969		for ( j=0; j<num_values; j++ ) {
1970			/* pathname should be stored as <key>\<value> */
1971
1972			val = regval_ctr_specific_value( val_ctr, j );
1973			pstrcpy( path, data->keys[i].name );
1974			pstrcat( path, "\\" );
1975			pstrcat( path, regval_name(val) );
1976
1977			len += tdb_pack(buf+len, buflen-len, "pPdB",
1978					val,
1979					path,
1980					regval_type(val),
1981					regval_size(val),
1982					regval_data_p(val) );
1983		}
1984
1985	}
1986
1987	/* terminator */
1988
1989	len += tdb_pack(buf+len, buflen-len, "p", NULL);
1990
1991	return len;
1992}
1993
1994
1995/****************************************************************************
1996 Delete a printer - this just deletes the printer info file, any open
1997 handles are not affected.
1998****************************************************************************/
1999
2000uint32 del_a_printer(char *sharename)
2001{
2002	pstring key;
2003	TDB_DATA kbuf;
2004
2005	slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2006
2007	kbuf.dptr=key;
2008	kbuf.dsize=strlen(key)+1;
2009
2010	tdb_delete(tdb_printers, kbuf);
2011	return 0;
2012}
2013
2014/* FIXME!!!  Reorder so this forward declaration is not necessary --jerry */
2015static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2016static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2017/****************************************************************************
2018****************************************************************************/
2019static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2020{
2021	pstring key;
2022	char *buf;
2023	int buflen, len;
2024	WERROR ret;
2025	TDB_DATA kbuf, dbuf;
2026
2027	/*
2028	 * in addprinter: no servername and the printer is the name
2029	 * in setprinter: servername is \\server
2030	 *                and printer is \\server\\printer
2031	 *
2032	 * Samba manages only local printers.
2033	 * we currently don't support things like path=\\other_server\printer
2034	 */
2035
2036	if (info->servername[0]!='\0') {
2037		trim_string(info->printername, info->servername, NULL);
2038		trim_char(info->printername, '\\', '\0');
2039		info->servername[0]='\0';
2040	}
2041
2042	/*
2043	 * JFM: one day I'll forget.
2044	 * below that's info->portname because that's the SAMBA sharename
2045	 * and I made NT 'thinks' it's the portname
2046	 * the info->sharename is the thing you can name when you add a printer
2047	 * that's the short-name when you create shared printer for 95/98
2048	 * So I've made a limitation in SAMBA: you can only have 1 printer model
2049	 * behind a SAMBA share.
2050	 */
2051
2052	buf = NULL;
2053	buflen = 0;
2054
2055 again:
2056	len = 0;
2057	len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2058			info->attributes,
2059			info->priority,
2060			info->default_priority,
2061			info->starttime,
2062			info->untiltime,
2063			info->status,
2064			info->cjobs,
2065			info->averageppm,
2066			info->changeid,
2067			info->c_setprinter,
2068			info->setuptime,
2069			info->servername,
2070			info->printername,
2071			info->sharename,
2072			info->portname,
2073			info->drivername,
2074			info->comment,
2075			info->location,
2076			info->sepfile,
2077			info->printprocessor,
2078			info->datatype,
2079			info->parameters);
2080
2081	len += pack_devicemode(info->devmode, buf+len, buflen-len);
2082
2083	len += pack_values( &info->data, buf+len, buflen-len );
2084
2085	if (buflen != len) {
2086		char *tb;
2087
2088		tb = (char *)Realloc(buf, len);
2089		if (!tb) {
2090			DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2091			ret = WERR_NOMEM;
2092			goto done;
2093		}
2094		else buf = tb;
2095		buflen = len;
2096		goto again;
2097	}
2098
2099
2100	slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2101
2102	kbuf.dptr = key;
2103	kbuf.dsize = strlen(key)+1;
2104	dbuf.dptr = buf;
2105	dbuf.dsize = len;
2106
2107	ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2108
2109done:
2110	if (!W_ERROR_IS_OK(ret))
2111		DEBUG(8, ("error updating printer to tdb on disk\n"));
2112
2113	SAFE_FREE(buf);
2114
2115	DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2116		 info->sharename, info->drivername, info->portname, len));
2117
2118	return ret;
2119}
2120
2121
2122/****************************************************************************
2123 Malloc and return an NT devicemode.
2124****************************************************************************/
2125
2126NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2127{
2128
2129	char adevice[MAXDEVICENAME];
2130	NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2131
2132	if (nt_devmode == NULL) {
2133		DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2134		return NULL;
2135	}
2136
2137	ZERO_STRUCTP(nt_devmode);
2138
2139	safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2140	fstrcpy(nt_devmode->devicename, adevice);
2141
2142	fstrcpy(nt_devmode->formname, "Letter");
2143
2144	nt_devmode->specversion      = 0x0401;
2145	nt_devmode->driverversion    = 0x0400;
2146	nt_devmode->size             = 0x00DC;
2147	nt_devmode->driverextra      = 0x0000;
2148	nt_devmode->fields           = FORMNAME | TTOPTION | PRINTQUALITY |
2149				       DEFAULTSOURCE | COPIES | SCALE |
2150				       PAPERSIZE | ORIENTATION;
2151	nt_devmode->orientation      = 1;
2152	nt_devmode->papersize        = PAPER_LETTER;
2153	nt_devmode->paperlength      = 0;
2154	nt_devmode->paperwidth       = 0;
2155	nt_devmode->scale            = 0x64;
2156	nt_devmode->copies           = 1;
2157	nt_devmode->defaultsource    = BIN_FORMSOURCE;
2158	nt_devmode->printquality     = RES_HIGH;           /* 0x0258 */
2159	nt_devmode->color            = COLOR_MONOCHROME;
2160	nt_devmode->duplex           = DUP_SIMPLEX;
2161	nt_devmode->yresolution      = 0;
2162	nt_devmode->ttoption         = TT_SUBDEV;
2163	nt_devmode->collate          = COLLATE_FALSE;
2164	nt_devmode->icmmethod        = 0;
2165	nt_devmode->icmintent        = 0;
2166	nt_devmode->mediatype        = 0;
2167	nt_devmode->dithertype       = 0;
2168
2169	/* non utilis�s par un driver d'imprimante */
2170	nt_devmode->logpixels        = 0;
2171	nt_devmode->bitsperpel       = 0;
2172	nt_devmode->pelswidth        = 0;
2173	nt_devmode->pelsheight       = 0;
2174	nt_devmode->displayflags     = 0;
2175	nt_devmode->displayfrequency = 0;
2176	nt_devmode->reserved1        = 0;
2177	nt_devmode->reserved2        = 0;
2178	nt_devmode->panningwidth     = 0;
2179	nt_devmode->panningheight    = 0;
2180
2181	nt_devmode->private = NULL;
2182	return nt_devmode;
2183}
2184
2185/****************************************************************************
2186 Deepcopy an NT devicemode.
2187****************************************************************************/
2188
2189NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2190{
2191	NT_DEVICEMODE *new_nt_devicemode = NULL;
2192
2193	if ( !nt_devicemode )
2194		return NULL;
2195
2196	if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2197		DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2198		return NULL;
2199	}
2200
2201	new_nt_devicemode->private = NULL;
2202	if (nt_devicemode->private != NULL) {
2203		if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2204			SAFE_FREE(new_nt_devicemode);
2205			DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2206			return NULL;
2207        }
2208	}
2209
2210	return new_nt_devicemode;
2211}
2212
2213/****************************************************************************
2214 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2215****************************************************************************/
2216
2217void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2218{
2219	NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2220
2221	if(nt_devmode == NULL)
2222		return;
2223
2224	DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2225
2226	SAFE_FREE(nt_devmode->private);
2227	SAFE_FREE(*devmode_ptr);
2228}
2229
2230/****************************************************************************
2231 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2232****************************************************************************/
2233static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2234{
2235	NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2236	NT_PRINTER_DATA		*data;
2237	int 			i;
2238
2239	if ( !info )
2240		return;
2241
2242	DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2243
2244	free_nt_devicemode(&info->devmode);
2245
2246	/* clean up all registry keys */
2247
2248	data = &info->data;
2249	for ( i=0; i<data->num_keys; i++ ) {
2250		SAFE_FREE( data->keys[i].name );
2251		regval_ctr_destroy( &data->keys[i].values );
2252	}
2253	SAFE_FREE( data->keys );
2254
2255	/* finally the top level structure */
2256
2257	SAFE_FREE( *info_ptr );
2258}
2259
2260
2261/****************************************************************************
2262****************************************************************************/
2263int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2264{
2265	int len = 0;
2266	int extra_len = 0;
2267	NT_DEVICEMODE devmode;
2268
2269	ZERO_STRUCT(devmode);
2270
2271	len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2272
2273	if (!*nt_devmode) return len;
2274
2275	len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2276			  devmode.devicename,
2277			  devmode.formname,
2278
2279			  &devmode.specversion,
2280			  &devmode.driverversion,
2281			  &devmode.size,
2282			  &devmode.driverextra,
2283			  &devmode.orientation,
2284			  &devmode.papersize,
2285			  &devmode.paperlength,
2286			  &devmode.paperwidth,
2287			  &devmode.scale,
2288			  &devmode.copies,
2289			  &devmode.defaultsource,
2290			  &devmode.printquality,
2291			  &devmode.color,
2292			  &devmode.duplex,
2293			  &devmode.yresolution,
2294			  &devmode.ttoption,
2295			  &devmode.collate,
2296			  &devmode.logpixels,
2297
2298			  &devmode.fields,
2299			  &devmode.bitsperpel,
2300			  &devmode.pelswidth,
2301			  &devmode.pelsheight,
2302			  &devmode.displayflags,
2303			  &devmode.displayfrequency,
2304			  &devmode.icmmethod,
2305			  &devmode.icmintent,
2306			  &devmode.mediatype,
2307			  &devmode.dithertype,
2308			  &devmode.reserved1,
2309			  &devmode.reserved2,
2310			  &devmode.panningwidth,
2311			  &devmode.panningheight,
2312			  &devmode.private);
2313
2314	if (devmode.private) {
2315		/* the len in tdb_unpack is an int value and
2316		 * devmode.driverextra is only a short
2317		 */
2318		len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2319		devmode.driverextra=(uint16)extra_len;
2320
2321		/* check to catch an invalid TDB entry so we don't segfault */
2322		if (devmode.driverextra == 0) {
2323			devmode.private = NULL;
2324		}
2325	}
2326
2327	*nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2328
2329	DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2330	if (devmode.private)
2331		DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2332
2333	return len;
2334}
2335
2336/****************************************************************************
2337 Allocate and initialize a new slot.
2338***************************************************************************/
2339
2340static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2341{
2342	NT_PRINTER_KEY	*d;
2343	int		key_index;
2344
2345	if ( !data || !name )
2346		return -1;
2347
2348	/* allocate another slot in the NT_PRINTER_KEY array */
2349
2350	d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2351	if ( d )
2352		data->keys = d;
2353
2354	key_index = data->num_keys;
2355
2356	/* initialze new key */
2357
2358	data->num_keys++;
2359	data->keys[key_index].name = strdup( name );
2360
2361	ZERO_STRUCTP( &data->keys[key_index].values );
2362
2363	regval_ctr_init( &data->keys[key_index].values );
2364
2365	DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2366
2367	return key_index;
2368}
2369
2370/****************************************************************************
2371 search for a registry key name in the existing printer data
2372 ***************************************************************************/
2373
2374int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2375{
2376	int		key_index = -1;
2377	int		i;
2378
2379	if ( !data || !name )
2380		return -1;
2381
2382	DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2383
2384	/* loop over all existing keys */
2385
2386	for ( i=0; i<data->num_keys; i++ ) {
2387		if ( strequal(data->keys[i].name, name) ) {
2388			DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2389			key_index = i;
2390			break;
2391
2392		}
2393	}
2394
2395	return key_index;
2396}
2397
2398/****************************************************************************
2399 ***************************************************************************/
2400
2401uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2402{
2403	int	i, j;
2404	int	key_len;
2405	int	num_subkeys = 0;
2406	char	*p;
2407	fstring	*ptr, *subkeys_ptr = NULL;
2408	fstring subkeyname;
2409
2410	if ( !data )
2411		return 0;
2412
2413	for ( i=0; i<data->num_keys; i++ ) {
2414		if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2415			/* match sure it is a subkey and not the key itself */
2416
2417			key_len = strlen( key );
2418			if ( strlen(data->keys[i].name) == key_len )
2419				continue;
2420
2421			/* get subkey path */
2422
2423			p = data->keys[i].name + key_len;
2424			if ( *p == '\\' )
2425				p++;
2426			fstrcpy( subkeyname, p );
2427			if ( (p = strchr( subkeyname, '\\' )) )
2428				*p = '\0';
2429
2430			/* don't add a key more than once */
2431
2432			for ( j=0; j<num_subkeys; j++ ) {
2433				if ( strequal( subkeys_ptr[j], subkeyname ) )
2434					break;
2435			}
2436
2437			if ( j != num_subkeys )
2438				continue;
2439
2440			/* found a match, so allocate space and copy the name */
2441
2442			if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2443				DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2444					num_subkeys+1));
2445				SAFE_FREE( subkeys );
2446				return 0;
2447			}
2448
2449			subkeys_ptr = ptr;
2450			fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2451			num_subkeys++;
2452		}
2453
2454	}
2455
2456	/* tag of the end */
2457
2458	if (num_subkeys)
2459		fstrcpy(subkeys_ptr[num_subkeys], "" );
2460
2461	*subkeys = subkeys_ptr;
2462
2463	return num_subkeys;
2464}
2465
2466#ifdef HAVE_ADS
2467static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2468			    const char *sz)
2469{
2470	smb_ucs2_t conv_str[1024];
2471	size_t str_size;
2472
2473	regval_ctr_delvalue(ctr, val_name);
2474	str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2475			     STR_TERMINATE | STR_NOALIGN);
2476	regval_ctr_addvalue(ctr, val_name, REG_SZ,
2477			    (char *) conv_str, str_size);
2478}
2479
2480static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2481			       uint32 dword)
2482{
2483	regval_ctr_delvalue(ctr, val_name);
2484	regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2485			    (char *) &dword, sizeof(dword));
2486}
2487
2488static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2489			      BOOL b)
2490{
2491	uint8 bin_bool = (b ? 1 : 0);
2492	regval_ctr_delvalue(ctr, val_name);
2493	regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2494			    (char *) &bin_bool, sizeof(bin_bool));
2495}
2496
2497static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2498					 const char *multi_sz)
2499{
2500	smb_ucs2_t *conv_strs = NULL;
2501	size_t str_size;
2502
2503	/* a multi-sz has to have a null string terminator, i.e., the last
2504	   string must be followed by two nulls */
2505	str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2506	conv_strs = calloc(str_size, 1);
2507
2508	push_ucs2(NULL, conv_strs, multi_sz, str_size,
2509		  STR_TERMINATE | STR_NOALIGN);
2510
2511	regval_ctr_delvalue(ctr, val_name);
2512	regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2513			    (char *) conv_strs, str_size);
2514	safe_free(conv_strs);
2515
2516}
2517
2518/****************************************************************************
2519 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2520 *
2521 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2522 * @return BOOL indicating success or failure
2523 ***************************************************************************/
2524
2525static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2526{
2527	REGVAL_CTR *ctr = NULL;
2528	fstring longname;
2529	char *allocated_string = NULL;
2530        const char *ascii_str;
2531	int i;
2532
2533	if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2534		i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2535	ctr = &info2->data.keys[i].values;
2536
2537	map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2538	map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2539
2540	get_myfullname(longname);
2541	map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2542
2543	asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2544	map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2545	SAFE_FREE(allocated_string);
2546
2547	map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2548	map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2549	map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2550	map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2551	map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2552	map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2553	map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2554	map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2555	map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2556
2557	map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2558			  (info2->attributes &
2559			   PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2560
2561	switch (info2->attributes & 0x3) {
2562	case 0:
2563		ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2564		break;
2565	case 1:
2566		ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2567		break;
2568	case 2:
2569		ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2570		break;
2571	default:
2572		ascii_str = "unknown";
2573	}
2574	map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2575
2576	return True;
2577}
2578
2579static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2580{
2581	int i;
2582	REGVAL_CTR *ctr=NULL;
2583
2584	/* find the DsSpooler key */
2585	if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2586		i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2587	ctr = &info2->data.keys[i].values;
2588
2589	regval_ctr_delvalue(ctr, "objectGUID");
2590	regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2591			    (char *) &guid, sizeof(GUID));
2592}
2593
2594static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2595{
2596	ADS_STATUS ads_rc;
2597	TALLOC_CTX *ctx = talloc_init("publish_it");
2598	ADS_MODLIST mods = ads_init_mods(ctx);
2599	char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2600	char *srv_dn_utf8, **srv_cn_utf8;
2601	void *res = NULL;
2602	ADS_STRUCT *ads;
2603	const char *attrs[] = {"objectGUID", NULL};
2604	GUID guid;
2605	WERROR win_rc = WERR_OK;
2606
2607	ZERO_STRUCT(guid);
2608	/* set the DsSpooler info and attributes */
2609	if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2610			return WERR_NOMEM;
2611	printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2612	win_rc = mod_a_printer(*printer, 2);
2613	if (!W_ERROR_IS_OK(win_rc)) {
2614		DEBUG(3, ("err %d saving data\n",
2615				  W_ERROR_V(win_rc)));
2616		return win_rc;
2617	}
2618
2619	/* Build the ads mods */
2620	get_local_printer_publishing_data(ctx, &mods,
2621					  &printer->info_2->data);
2622	ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2623		    printer->info_2->sharename);
2624
2625	/* initial ads structure */
2626
2627	ads = ads_init(NULL, NULL, NULL);
2628	if (!ads) {
2629		DEBUG(3, ("ads_init() failed\n"));
2630		return WERR_SERVER_UNAVAILABLE;
2631	}
2632	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2633	SAFE_FREE(ads->auth.password);
2634	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2635		NULL, NULL);
2636
2637	/* ads_connect() will find the DC for us */
2638	ads_rc = ads_connect(ads);
2639	if (!ADS_ERR_OK(ads_rc)) {
2640		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2641		ads_destroy(&ads);
2642		return WERR_ACCESS_DENIED;
2643	}
2644
2645	/* figure out where to publish */
2646	ads_find_machine_acct(ads, &res, global_myname());
2647
2648	/* We use ldap_get_dn here as we need the answer
2649	 * in utf8 to call ldap_explode_dn(). JRA. */
2650
2651	srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2652	if (!srv_dn_utf8) {
2653		ads_destroy(&ads);
2654		return WERR_SERVER_UNAVAILABLE;
2655	}
2656	ads_msgfree(ads, res);
2657	srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2658	if (!srv_cn_utf8) {
2659		ldap_memfree(srv_dn_utf8);
2660		ads_destroy(&ads);
2661		return WERR_SERVER_UNAVAILABLE;
2662	}
2663	/* Now convert to CH_UNIX. */
2664	if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2665		ldap_memfree(srv_dn_utf8);
2666		ldap_memfree(srv_cn_utf8);
2667		ads_destroy(&ads);
2668		return WERR_SERVER_UNAVAILABLE;
2669	}
2670	if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2671		ldap_memfree(srv_dn_utf8);
2672		ldap_memfree(srv_cn_utf8);
2673		ads_destroy(&ads);
2674		SAFE_FREE(srv_dn);
2675		return WERR_SERVER_UNAVAILABLE;
2676	}
2677
2678	ldap_memfree(srv_dn_utf8);
2679	ldap_memfree(srv_cn_utf8);
2680
2681	asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2682		 printer->info_2->sharename, srv_dn);
2683
2684	SAFE_FREE(srv_dn);
2685	SAFE_FREE(srv_cn_0);
2686
2687	/* publish it */
2688	ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2689	if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2690		ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2691
2692	/* retreive the guid and store it locally */
2693	if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2694		ads_memfree(ads, prt_dn);
2695		ads_pull_guid(ads, res, &guid);
2696		ads_msgfree(ads, res);
2697		store_printer_guid(printer->info_2, guid);
2698		win_rc = mod_a_printer(*printer, 2);
2699	}
2700
2701	safe_free(prt_dn);
2702	ads_destroy(&ads);
2703
2704	return WERR_OK;
2705}
2706
2707WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2708{
2709	ADS_STATUS ads_rc;
2710	ADS_STRUCT *ads;
2711	void *res;
2712	char *prt_dn = NULL;
2713	WERROR win_rc;
2714
2715	printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2716	win_rc = mod_a_printer(*printer, 2);
2717	if (!W_ERROR_IS_OK(win_rc)) {
2718		DEBUG(3, ("err %d saving data\n",
2719				  W_ERROR_V(win_rc)));
2720		return win_rc;
2721	}
2722
2723	ads = ads_init(NULL, NULL, NULL);
2724	if (!ads) {
2725		DEBUG(3, ("ads_init() failed\n"));
2726		return WERR_SERVER_UNAVAILABLE;
2727	}
2728	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2729	SAFE_FREE(ads->auth.password);
2730	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2731		NULL, NULL);
2732
2733	/* ads_connect() will find the DC for us */
2734	ads_rc = ads_connect(ads);
2735	if (!ADS_ERR_OK(ads_rc)) {
2736		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2737		ads_destroy(&ads);
2738		return WERR_ACCESS_DENIED;
2739	}
2740
2741	/* remove the printer from the directory */
2742	ads_rc = ads_find_printer_on_server(ads, &res,
2743			    printer->info_2->sharename, global_myname());
2744	if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2745		prt_dn = ads_get_dn(ads, res);
2746		ads_msgfree(ads, res);
2747		ads_rc = ads_del_dn(ads, prt_dn);
2748		ads_memfree(ads, prt_dn);
2749	}
2750
2751	ads_destroy(&ads);
2752	return WERR_OK;
2753}
2754
2755/****************************************************************************
2756 * Publish a printer in the directory
2757 *
2758 * @param snum describing printer service
2759 * @return WERROR indicating status of publishing
2760 ***************************************************************************/
2761
2762WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2763{
2764	NT_PRINTER_INFO_LEVEL *printer = NULL;
2765	WERROR win_rc;
2766
2767	win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2768	if (!W_ERROR_IS_OK(win_rc))
2769		return win_rc;
2770
2771	switch(action) {
2772	case SPOOL_DS_PUBLISH:
2773	case SPOOL_DS_UPDATE:
2774		win_rc = publish_it(printer);
2775		break;
2776	case SPOOL_DS_UNPUBLISH:
2777		win_rc = unpublish_it(printer);
2778		break;
2779	default:
2780		win_rc = WERR_NOT_SUPPORTED;
2781	}
2782
2783
2784	free_a_printer(&printer, 2);
2785	return win_rc;
2786}
2787
2788BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2789{
2790	NT_PRINTER_INFO_LEVEL *printer = NULL;
2791	REGVAL_CTR *ctr;
2792	REGISTRY_VALUE *guid_val;
2793	WERROR win_rc;
2794	int i;
2795
2796
2797	win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2798	if (!W_ERROR_IS_OK(win_rc))
2799		return False;
2800
2801	if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2802		return False;
2803
2804	if ((i = lookup_printerkey(&printer->info_2->data,
2805				   SPOOL_DSSPOOLER_KEY)) < 0)
2806		return False;
2807
2808	if (!(ctr = &printer->info_2->data.keys[i].values)) {
2809		return False;
2810	}
2811
2812	if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2813		return False;
2814	}
2815
2816	if (regval_size(guid_val) == sizeof(GUID))
2817		memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2818
2819	return True;
2820}
2821
2822#else
2823WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2824{
2825	return WERR_OK;
2826}
2827BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2828{
2829	return False;
2830}
2831#endif
2832/****************************************************************************
2833 ***************************************************************************/
2834
2835WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2836{
2837	NT_PRINTER_DATA	*data;
2838	int		i;
2839	int		removed_keys = 0;
2840	int		empty_slot;
2841
2842	data = &p2->data;
2843	empty_slot = data->num_keys;
2844
2845	if ( !key )
2846		return WERR_INVALID_PARAM;
2847
2848	/* remove all keys */
2849
2850	if ( !strlen(key) ) {
2851		for ( i=0; i<data->num_keys; i++ ) {
2852			DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2853				data->keys[i].name));
2854
2855			SAFE_FREE( data->keys[i].name );
2856			regval_ctr_destroy( &data->keys[i].values );
2857		}
2858
2859		DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2860			p2->printername ));
2861
2862		SAFE_FREE( data->keys );
2863		ZERO_STRUCTP( data );
2864
2865		return WERR_OK;
2866	}
2867
2868	/* remove a specific key (and all subkeys) */
2869
2870	for ( i=0; i<data->num_keys; i++ ) {
2871		if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2872			DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2873				data->keys[i].name));
2874
2875			SAFE_FREE( data->keys[i].name );
2876			regval_ctr_destroy( &data->keys[i].values );
2877
2878			/* mark the slot as empty */
2879
2880			ZERO_STRUCTP( &data->keys[i] );
2881		}
2882	}
2883
2884	/* find the first empty slot */
2885
2886	for ( i=0; i<data->num_keys; i++ ) {
2887		if ( !data->keys[i].name ) {
2888			empty_slot = i;
2889			removed_keys++;
2890			break;
2891		}
2892	}
2893
2894	if ( i == data->num_keys )
2895		/* nothing was removed */
2896		return WERR_INVALID_PARAM;
2897
2898	/* move everything down */
2899
2900	for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2901		if ( data->keys[i].name ) {
2902			memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2903			ZERO_STRUCTP( &data->keys[i] );
2904			empty_slot++;
2905			removed_keys++;
2906		}
2907	}
2908
2909	/* update count */
2910
2911	data->num_keys -= removed_keys;
2912
2913	/* sanity check to see if anything is left */
2914
2915	if ( !data->num_keys ) {
2916		DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2917
2918		SAFE_FREE( data->keys );
2919		ZERO_STRUCTP( data );
2920	}
2921
2922	return WERR_OK;
2923}
2924
2925/****************************************************************************
2926 ***************************************************************************/
2927
2928WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2929{
2930	WERROR 		result = WERR_OK;
2931	int		key_index;
2932
2933	/* we must have names on non-zero length */
2934
2935	if ( !key || !*key|| !value || !*value )
2936		return WERR_INVALID_NAME;
2937
2938	/* find the printer key first */
2939
2940	key_index = lookup_printerkey( &p2->data, key );
2941	if ( key_index == -1 )
2942		return WERR_OK;
2943
2944	/* make sure the value exists so we can return the correct error code */
2945
2946	if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2947		return WERR_BADFILE;
2948
2949	regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2950
2951	DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2952		key, value ));
2953
2954	return result;
2955}
2956
2957/****************************************************************************
2958 ***************************************************************************/
2959
2960WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2961                           uint32 type, uint8 *data, int real_len )
2962{
2963	WERROR 		result = WERR_OK;
2964	int		key_index;
2965
2966	/* we must have names on non-zero length */
2967
2968	if ( !key || !*key|| !value || !*value )
2969		return WERR_INVALID_NAME;
2970
2971	/* find the printer key first */
2972
2973	key_index = lookup_printerkey( &p2->data, key );
2974	if ( key_index == -1 )
2975		key_index = add_new_printer_key( &p2->data, key );
2976
2977	if ( key_index == -1 )
2978		return WERR_NOMEM;
2979
2980	regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2981		type, (const char *)data, real_len );
2982
2983	DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2984		key, value, type, real_len  ));
2985
2986	return result;
2987}
2988
2989/****************************************************************************
2990 ***************************************************************************/
2991
2992REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2993{
2994	int		key_index;
2995
2996	if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2997		return NULL;
2998
2999	DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3000		key, value ));
3001
3002	return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3003}
3004
3005/****************************************************************************
3006 Unpack a list of registry values frem the TDB
3007 ***************************************************************************/
3008
3009static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3010{
3011	int 		len = 0;
3012	uint32		type;
3013	pstring		string, valuename, keyname;
3014	char		*str;
3015	int		size;
3016	uint8		*data_p;
3017	REGISTRY_VALUE 	*regval_p;
3018	int		key_index;
3019
3020	/* add the "PrinterDriverData" key first for performance reasons */
3021
3022	add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3023
3024	/* loop and unpack the rest of the registry values */
3025
3026	while ( True ) {
3027
3028		/* check to see if there are any more registry values */
3029
3030		len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3031		if ( !regval_p )
3032			break;
3033
3034		/* unpack the next regval */
3035
3036		len += tdb_unpack(buf+len, buflen-len, "fdB",
3037				  string,
3038				  &type,
3039				  &size,
3040				  &data_p);
3041
3042		/*
3043		 * break of the keyname from the value name.
3044		 * Should only be one '\' in the string returned.
3045		 */
3046
3047		str = strrchr( string, '\\');
3048
3049		/* Put in "PrinterDriverData" is no key specified */
3050
3051		if ( !str ) {
3052			pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3053			pstrcpy( valuename, string );
3054		}
3055		else {
3056			*str = '\0';
3057			pstrcpy( keyname, string );
3058			pstrcpy( valuename, str+1 );
3059		}
3060
3061		/* see if we need a new key */
3062
3063		if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3064			key_index = add_new_printer_key( printer_data, keyname );
3065
3066		if ( key_index == -1 ) {
3067			DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3068				keyname));
3069			break;
3070		}
3071
3072		/* add the new value */
3073
3074		regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3075
3076		SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3077
3078		DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3079	}
3080
3081	return len;
3082}
3083
3084/****************************************************************************
3085 ***************************************************************************/
3086
3087static void map_to_os2_driver(fstring drivername)
3088{
3089	static BOOL initialised=False;
3090	static fstring last_from,last_to;
3091	char *mapfile = lp_os2_driver_map();
3092	char **lines = NULL;
3093	int numlines = 0;
3094	int i;
3095
3096	if (!strlen(drivername))
3097		return;
3098
3099	if (!*mapfile)
3100		return;
3101
3102	if (!initialised) {
3103		*last_from = *last_to = 0;
3104		initialised = True;
3105	}
3106
3107	if (strequal(drivername,last_from)) {
3108		DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3109		fstrcpy(drivername,last_to);
3110		return;
3111	}
3112
3113	lines = file_lines_load(mapfile, &numlines);
3114	if (numlines == 0) {
3115		DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3116		return;
3117	}
3118
3119	DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3120
3121	for( i = 0; i < numlines; i++) {
3122		char *nt_name = lines[i];
3123		char *os2_name = strchr(nt_name,'=');
3124
3125		if (!os2_name)
3126			continue;
3127
3128		*os2_name++ = 0;
3129
3130		while (isspace(*nt_name))
3131			nt_name++;
3132
3133		if (!*nt_name || strchr("#;",*nt_name))
3134			continue;
3135
3136		{
3137			int l = strlen(nt_name);
3138			while (l && isspace(nt_name[l-1])) {
3139				nt_name[l-1] = 0;
3140				l--;
3141			}
3142		}
3143
3144		while (isspace(*os2_name))
3145			os2_name++;
3146
3147		{
3148			int l = strlen(os2_name);
3149			while (l && isspace(os2_name[l-1])) {
3150				os2_name[l-1] = 0;
3151				l--;
3152			}
3153		}
3154
3155		if (strequal(nt_name,drivername)) {
3156			DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3157			fstrcpy(last_from,drivername);
3158			fstrcpy(last_to,os2_name);
3159			fstrcpy(drivername,os2_name);
3160			file_lines_free(lines);
3161			return;
3162		}
3163	}
3164
3165	file_lines_free(lines);
3166}
3167
3168/****************************************************************************
3169 Get a default printer info 2 struct.
3170****************************************************************************/
3171static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3172{
3173	int snum;
3174	NT_PRINTER_INFO_LEVEL_2 info;
3175
3176	ZERO_STRUCT(info);
3177
3178	snum = lp_servicenumber(sharename);
3179
3180	slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3181	slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3182		 get_called_name(), sharename);
3183	fstrcpy(info.sharename, sharename);
3184	fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3185
3186	/* by setting the driver name to an empty string, a local NT admin
3187	   can now run the **local** APW to install a local printer driver
3188 	   for a Samba shared printer in 2.2.  Without this, drivers **must** be
3189	   installed on the Samba server for NT clients --jerry */
3190#if 0	/* JERRY --do not uncomment-- */
3191	if (!*info.drivername)
3192		fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3193#endif
3194
3195
3196	DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3197
3198	pstrcpy(info.comment, "");
3199	fstrcpy(info.printprocessor, "winprint");
3200	fstrcpy(info.datatype, "RAW");
3201
3202	info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3203
3204	info.starttime = 0; /* Minutes since 12:00am GMT */
3205	info.untiltime = 0; /* Minutes since 12:00am GMT */
3206	info.priority = 1;
3207	info.default_priority = 1;
3208	info.setuptime = (uint32)time(NULL);
3209
3210	/*
3211	 * I changed this as I think it is better to have a generic
3212	 * DEVMODE than to crash Win2k explorer.exe   --jerry
3213	 * See the HP Deskjet 990c Win2k drivers for an example.
3214	 *
3215	 * However the default devmode appears to cause problems
3216	 * with the HP CLJ 8500 PCL driver.  Hence the addition of
3217	 * the "default devmode" parameter   --jerry 22/01/2002
3218	 */
3219
3220	if (lp_default_devmode(snum)) {
3221		if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3222			goto fail;
3223	}
3224	else {
3225		info.devmode = NULL;
3226	}
3227
3228	/* This will get the current RPC talloc context, but we should be
3229	   passing this as a parameter... fixme... JRA ! */
3230
3231	if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3232		goto fail;
3233
3234	*info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3235	if (! *info_ptr) {
3236		DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3237		goto fail;
3238	}
3239
3240	return WERR_OK;
3241
3242  fail:
3243	if (info.devmode)
3244		free_nt_devicemode(&info.devmode);
3245	return WERR_ACCESS_DENIED;
3246}
3247
3248/****************************************************************************
3249****************************************************************************/
3250static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3251{
3252	pstring key;
3253	NT_PRINTER_INFO_LEVEL_2 info;
3254	int 		len = 0;
3255	TDB_DATA kbuf, dbuf;
3256	fstring printername;
3257	char adevice[MAXDEVICENAME];
3258
3259	ZERO_STRUCT(info);
3260
3261	slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3262
3263	kbuf.dptr = key;
3264	kbuf.dsize = strlen(key)+1;
3265
3266	dbuf = tdb_fetch(tdb_printers, kbuf);
3267	if (!dbuf.dptr)
3268		return get_a_printer_2_default(info_ptr, sharename);
3269
3270	len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3271			&info.attributes,
3272			&info.priority,
3273			&info.default_priority,
3274			&info.starttime,
3275			&info.untiltime,
3276			&info.status,
3277			&info.cjobs,
3278			&info.averageppm,
3279			&info.changeid,
3280			&info.c_setprinter,
3281			&info.setuptime,
3282			info.servername,
3283			info.printername,
3284			info.sharename,
3285			info.portname,
3286			info.drivername,
3287			info.comment,
3288			info.location,
3289			info.sepfile,
3290			info.printprocessor,
3291			info.datatype,
3292			info.parameters);
3293
3294	/* Samba has to have shared raw drivers. */
3295	info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3296
3297	/* Restore the stripped strings. */
3298	slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3299	slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3300			info.printername);
3301	fstrcpy(info.printername, printername);
3302
3303	len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3304
3305	/*
3306	 * Some client drivers freak out if there is a NULL devmode
3307	 * (probably the driver is not checking before accessing
3308	 * the devmode pointer)   --jerry
3309	 *
3310	 * See comments in get_a_printer_2_default()
3311	 */
3312
3313	if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3314		DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3315			printername));
3316		info.devmode = construct_nt_devicemode(printername);
3317	}
3318
3319	safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3320	if (info.devmode) {
3321		fstrcpy(info.devmode->devicename, adevice);
3322	}
3323
3324	len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3325
3326	/* This will get the current RPC talloc context, but we should be
3327	   passing this as a parameter... fixme... JRA ! */
3328
3329	nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3330
3331	/* Fix for OS/2 drivers. */
3332
3333	if (get_remote_arch() == RA_OS2)
3334		map_to_os2_driver(info.drivername);
3335
3336	SAFE_FREE(dbuf.dptr);
3337	*info_ptr=memdup(&info, sizeof(info));
3338
3339	DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3340		 sharename, info.printername, info.drivername));
3341
3342	return WERR_OK;
3343}
3344
3345/****************************************************************************
3346 Debugging function, dump at level 6 the struct in the logs.
3347****************************************************************************/
3348static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3349{
3350	uint32 result;
3351	NT_PRINTER_INFO_LEVEL_2	*info2;
3352
3353	DEBUG(106,("Dumping printer at level [%d]\n", level));
3354
3355	switch (level) {
3356		case 2:
3357		{
3358			if (printer.info_2 == NULL)
3359				result=5;
3360			else
3361			{
3362				info2=printer.info_2;
3363
3364				DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3365				DEBUGADD(106,("priority:[%d]\n", info2->priority));
3366				DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3367				DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3368				DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3369				DEBUGADD(106,("status:[%d]\n", info2->status));
3370				DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3371				DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3372				DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3373				DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3374				DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3375
3376				DEBUGADD(106,("servername:[%s]\n", info2->servername));
3377				DEBUGADD(106,("printername:[%s]\n", info2->printername));
3378				DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3379				DEBUGADD(106,("portname:[%s]\n", info2->portname));
3380				DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3381				DEBUGADD(106,("comment:[%s]\n", info2->comment));
3382				DEBUGADD(106,("location:[%s]\n", info2->location));
3383				DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3384				DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3385				DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3386				DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3387				result=0;
3388			}
3389			break;
3390		}
3391		default:
3392			DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3393			result=1;
3394			break;
3395	}
3396
3397	return result;
3398}
3399
3400/****************************************************************************
3401 Update the changeid time.
3402 This is SO NASTY as some drivers need this to change, others need it
3403 static. This value will change every second, and I must hope that this
3404 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3405 UTAH ! JRA.
3406****************************************************************************/
3407
3408static uint32 rev_changeid(void)
3409{
3410	struct timeval tv;
3411
3412	get_process_uptime(&tv);
3413
3414#if 1	/* JERRY */
3415	/* Return changeid as msec since spooler restart */
3416	return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3417#else
3418	/*
3419	 * This setting seems to work well but is too untested
3420	 * to replace the above calculation.  Left in for experiementation
3421	 * of the reader            --jerry (Tue Mar 12 09:15:05 CST 2002)
3422	 */
3423	return tv.tv_sec * 10 + tv.tv_usec / 100000;
3424#endif
3425}
3426
3427/*
3428 * The function below are the high level ones.
3429 * only those ones must be called from the spoolss code.
3430 * JFM.
3431 */
3432
3433/****************************************************************************
3434 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3435****************************************************************************/
3436
3437WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3438{
3439	WERROR result;
3440
3441	dump_a_printer(printer, level);
3442
3443	/*
3444	 * invalidate cache for all open handles to this printer.
3445	 * cache for a given handle will be updated on the next
3446	 * get_a_printer()
3447	 */
3448
3449	invalidate_printer_hnd_cache( printer.info_2->sharename );
3450
3451	switch (level) {
3452		case 2:
3453		{
3454			/*
3455			 * Update the changestamp.  Emperical tests show that the
3456			 * ChangeID is always updated,but c_setprinter is
3457			 *  global spooler variable (not per printer).
3458			 */
3459
3460			/* ChangeID **must** be increasing over the lifetime
3461			   of client's spoolss service in order for the
3462			   client's cache to show updates */
3463
3464			printer.info_2->changeid = rev_changeid();
3465
3466			/*
3467			 * Because one day someone will ask:
3468			 * NT->NT	An admin connection to a remote
3469			 * 		printer show changes imeediately in
3470			 * 		the properities dialog
3471			 *
3472			 * 		A non-admin connection will only show the
3473			 * 		changes after viewing the properites page
3474			 * 		2 times.  Seems to be related to a
3475			 * 		race condition in the client between the spooler
3476			 * 		updating the local cache and the Explorer.exe GUI
3477			 *		actually displaying the properties.
3478			 *
3479			 *		This is fixed in Win2k.  admin/non-admin
3480			 * 		connections both display changes immediately.
3481			 *
3482			 * 14/12/01	--jerry
3483			 */
3484
3485			result=update_a_printer_2(printer.info_2);
3486
3487			break;
3488		}
3489		default:
3490			result=WERR_UNKNOWN_LEVEL;
3491			break;
3492	}
3493
3494	return result;
3495}
3496
3497/****************************************************************************
3498 Initialize printer devmode & data with previously saved driver init values.
3499****************************************************************************/
3500
3501static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3502{
3503	int                     len = 0;
3504	pstring                 key;
3505	TDB_DATA                kbuf, dbuf;
3506	NT_PRINTER_INFO_LEVEL_2 info;
3507
3508
3509	ZERO_STRUCT(info);
3510
3511	/*
3512	 * Delete any printer data 'values' already set. When called for driver
3513	 * replace, there will generally be some, but during an add printer, there
3514	 * should not be any (if there are delete them).
3515	 */
3516
3517	delete_all_printer_data( info_ptr, "" );
3518
3519	slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3520
3521	kbuf.dptr = key;
3522	kbuf.dsize = strlen(key)+1;
3523
3524	dbuf = tdb_fetch(tdb_drivers, kbuf);
3525	if (!dbuf.dptr) {
3526		/*
3527		 * When changing to a driver that has no init info in the tdb, remove
3528		 * the previous drivers init info and leave the new on blank.
3529		 */
3530		free_nt_devicemode(&info_ptr->devmode);
3531		return False;
3532	}
3533
3534	/*
3535	 * Get the saved DEVMODE..
3536	 */
3537
3538	len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3539
3540	/*
3541	 * The saved DEVMODE contains the devicename from the printer used during
3542	 * the initialization save. Change it to reflect the new printer.
3543	 */
3544
3545	if ( info.devmode ) {
3546		ZERO_STRUCT(info.devmode->devicename);
3547		fstrcpy(info.devmode->devicename, info_ptr->printername);
3548	}
3549
3550	/*
3551	 * NT/2k does not change out the entire DeviceMode of a printer
3552	 * when changing the driver.  Only the driverextra, private, &
3553	 * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
3554	 *
3555	 * Later examination revealed that Windows NT/2k does reset the
3556	 * the printer's device mode, bit **only** when you change a
3557	 * property of the device mode such as the page orientation.
3558	 * --jerry
3559	 */
3560
3561
3562	/* Bind the saved DEVMODE to the new the printer */
3563
3564	free_nt_devicemode(&info_ptr->devmode);
3565	info_ptr->devmode = info.devmode;
3566
3567	DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3568		info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3569
3570	/* Add the printer data 'values' to the new printer */
3571
3572	len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3573
3574
3575	SAFE_FREE(dbuf.dptr);
3576
3577	return True;
3578}
3579
3580/****************************************************************************
3581 Initialize printer devmode & data with previously saved driver init values.
3582 When a printer is created using AddPrinter, the drivername bound to the
3583 printer is used to lookup previously saved driver initialization info, which
3584 is bound to the new printer.
3585****************************************************************************/
3586
3587BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3588{
3589	BOOL result = False;
3590
3591	switch (level) {
3592		case 2:
3593			result = set_driver_init_2(printer->info_2);
3594			break;
3595
3596		default:
3597			DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
3598				level));
3599			break;
3600	}
3601
3602	return result;
3603}
3604
3605/****************************************************************************
3606 Delete driver init data stored for a specified driver
3607****************************************************************************/
3608
3609BOOL del_driver_init(char *drivername)
3610{
3611	pstring key;
3612	TDB_DATA kbuf;
3613
3614	if (!drivername || !*drivername) {
3615		DEBUG(3,("del_driver_init: No drivername specified!\n"));
3616		return False;
3617	}
3618
3619	slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3620
3621	kbuf.dptr = key;
3622	kbuf.dsize = strlen(key)+1;
3623
3624	DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3625
3626	return (tdb_delete(tdb_drivers, kbuf) == 0);
3627}
3628
3629/****************************************************************************
3630 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3631 in the tdb. Note: this is different from the driver entry and the printer
3632 entry. There should be a single driver init entry for each driver regardless
3633 of whether it was installed from NT or 2K. Technically, they should be
3634 different, but they work out to the same struct.
3635****************************************************************************/
3636
3637static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3638{
3639	pstring key;
3640	char *buf;
3641	int buflen, len, ret;
3642	TDB_DATA kbuf, dbuf;
3643
3644	buf = NULL;
3645	buflen = 0;
3646
3647 again:
3648	len = 0;
3649	len += pack_devicemode(info->devmode, buf+len, buflen-len);
3650
3651	len += pack_values( &info->data, buf+len, buflen-len );
3652
3653	if (buflen != len) {
3654		char *tb;
3655
3656		tb = (char *)Realloc(buf, len);
3657		if (!tb) {
3658			DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3659			ret = -1;
3660			goto done;
3661		}
3662		else
3663			buf = tb;
3664		buflen = len;
3665		goto again;
3666	}
3667
3668	slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3669
3670	kbuf.dptr = key;
3671	kbuf.dsize = strlen(key)+1;
3672	dbuf.dptr = buf;
3673	dbuf.dsize = len;
3674
3675	ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3676
3677done:
3678	if (ret == -1)
3679		DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3680
3681	SAFE_FREE(buf);
3682
3683	DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3684		 info->sharename, info->drivername));
3685
3686	return ret;
3687}
3688
3689/****************************************************************************
3690 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3691****************************************************************************/
3692
3693uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3694{
3695	uint32 result;
3696
3697	dump_a_printer(printer, level);
3698
3699	switch (level) {
3700		case 2:
3701			result = update_driver_init_2(printer.info_2);
3702			break;
3703		default:
3704			result = 1;
3705			break;
3706	}
3707
3708	return result;
3709}
3710
3711/****************************************************************************
3712 Convert the printer data value, a REG_BINARY array, into an initialization
3713 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3714 got to keep the endians happy :).
3715****************************************************************************/
3716
3717static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3718{
3719	BOOL       result = False;
3720	prs_struct ps;
3721	DEVICEMODE devmode;
3722
3723	ZERO_STRUCT(devmode);
3724
3725	prs_init(&ps, 0, ctx, UNMARSHALL);
3726	ps.data_p      = (char *)data;
3727	ps.buffer_size = data_len;
3728
3729	if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3730		result = convert_devicemode("", &devmode, &nt_devmode);
3731	else
3732		DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3733
3734	return result;
3735}
3736
3737/****************************************************************************
3738 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3739
3740 1. Use the driver's config DLL to this UNC printername and:
3741    a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3742    b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3743 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3744
3745 The last step triggers saving the "driver initialization" information for
3746 this printer into the tdb. Later, new printers that use this driver will
3747 have this initialization information bound to them. This simulates the
3748 driver initialization, as if it had run on the Samba server (as it would
3749 have done on NT).
3750
3751 The Win32 client side code requirement sucks! But until we can run arbitrary
3752 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3753
3754 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3755 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3756 about it and you will realize why.  JRR 010720
3757****************************************************************************/
3758
3759static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3760{
3761	WERROR        status       = WERR_OK;
3762	TALLOC_CTX    *ctx         = NULL;
3763	NT_DEVICEMODE *nt_devmode  = NULL;
3764	NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3765
3766	/*
3767	 * When the DEVMODE is already set on the printer, don't try to unpack it.
3768	 */
3769	DEBUG(8,("save_driver_init_2: Enter...\n"));
3770
3771	if ( !printer->info_2->devmode && data_len ) {
3772		/*
3773		 * Set devmode on printer info, so entire printer initialization can be
3774		 * saved to tdb.
3775		 */
3776
3777		if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3778			return WERR_NOMEM;
3779
3780		if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3781			status = WERR_NOMEM;
3782			goto done;
3783		}
3784
3785		ZERO_STRUCTP(nt_devmode);
3786
3787		/*
3788		 * The DEVMODE is held in the 'data' component of the param in raw binary.
3789		 * Convert it to to a devmode structure
3790		 */
3791		if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3792			DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3793			status = WERR_INVALID_PARAM;
3794			goto done;
3795		}
3796
3797		printer->info_2->devmode = nt_devmode;
3798	}
3799
3800	/*
3801	 * Pack up and add (or update) the DEVMODE and any current printer data to
3802	 * a 'driver init' element in the tdb
3803	 *
3804	 */
3805
3806	if ( update_driver_init(*printer, 2) != 0 ) {
3807		DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3808		status = WERR_NOMEM;
3809		goto done;
3810	}
3811
3812	/*
3813	 * If driver initialization info was successfully saved, set the current
3814	 * printer to match it. This allows initialization of the current printer
3815	 * as well as the driver.
3816	 */
3817	status = mod_a_printer(*printer, 2);
3818	if (!W_ERROR_IS_OK(status)) {
3819		DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3820				  printer->info_2->printername));
3821	}
3822
3823  done:
3824	talloc_destroy(ctx);
3825	free_nt_devicemode( &nt_devmode );
3826
3827	printer->info_2->devmode = tmp_devmode;
3828
3829	return status;
3830}
3831
3832/****************************************************************************
3833 Update the driver init info (DEVMODE and specifics) for a printer
3834****************************************************************************/
3835
3836WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3837{
3838	WERROR status = WERR_OK;
3839
3840	switch (level) {
3841		case 2:
3842			status = save_driver_init_2( printer, data, data_len );
3843			break;
3844		default:
3845			status = WERR_UNKNOWN_LEVEL;
3846			break;
3847	}
3848
3849	return status;
3850}
3851
3852/****************************************************************************
3853 Deep copy a NT_PRINTER_DATA
3854****************************************************************************/
3855
3856static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3857{
3858	int i, j, num_vals, new_key_index;
3859	REGVAL_CTR *src_key, *dst_key;
3860
3861	if ( !dst || !src )
3862		return NT_STATUS_NO_MEMORY;
3863
3864	for ( i=0; i<src->num_keys; i++ ) {
3865
3866		/* create a new instance of the printerkey in the destination
3867		   printer_data object */
3868
3869		new_key_index = add_new_printer_key( dst, src->keys[i].name );
3870		dst_key = &dst->keys[new_key_index].values;
3871
3872		src_key = &src->keys[i].values;
3873		num_vals = regval_ctr_numvals( src_key );
3874
3875		/* dup the printer entire printer key */
3876
3877		for ( j=0; j<num_vals; j++ ) {
3878			regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3879		}
3880	}
3881
3882	return NT_STATUS_OK;
3883}
3884
3885/****************************************************************************
3886 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3887 Caller must free.
3888****************************************************************************/
3889
3890NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3891{
3892	NT_PRINTER_INFO_LEVEL_2 *copy;
3893
3894	if ( !printer )
3895		return NULL;
3896
3897	if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3898		return NULL;
3899
3900	memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3901
3902	/* malloc()'d members copied here */
3903
3904	copy->devmode = dup_nt_devicemode( printer->devmode );
3905
3906	ZERO_STRUCT( copy->data );
3907	copy_printer_data( &copy->data, &printer->data );
3908
3909	/* this is talloc()'d; very ugly that we have a structure that
3910	   is half malloc()'d and half talloc()'d but that is the way
3911	   that the PRINTER_INFO stuff is written right now.  --jerry  */
3912
3913	copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3914
3915	return copy;
3916}
3917
3918/****************************************************************************
3919 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3920
3921 Previously the code had a memory allocation problem because it always
3922 used the TALLOC_CTX from the Printer_entry*.   This context lasts
3923 as a long as the original handle is open.  So if the client made a lot
3924 of getprinter[data]() calls, the memory usage would climb.  Now we use
3925 a short lived TALLOC_CTX for printer_info_2 objects returned.  We
3926 still use the Printer_entry->ctx for maintaining the cache copy though
3927 since that object must live as long as the handle by definition.
3928                                                    --jerry
3929
3930****************************************************************************/
3931
3932WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3933			const char *sharename)
3934{
3935	WERROR result;
3936	NT_PRINTER_INFO_LEVEL *printer = NULL;
3937
3938	*pp_printer = NULL;
3939
3940	DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3941
3942	switch (level) {
3943		case 2:
3944			if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3945				DEBUG(0,("get_a_printer: malloc fail.\n"));
3946				return WERR_NOMEM;
3947			}
3948			ZERO_STRUCTP(printer);
3949
3950			/*
3951			 * check for cache first.  A Printer handle cannot changed
3952			 * to another printer object so we only check that the printer
3953			 * is actually for a printer and that the printer_info pointer
3954			 * is valid
3955			 */
3956			if ( print_hnd
3957				&& (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3958				&& print_hnd->printer_info )
3959			{
3960				/* get_talloc_ctx() works here because we need a short
3961				   lived talloc context */
3962
3963				if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
3964				{
3965					DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3966
3967					SAFE_FREE(printer);
3968					return WERR_NOMEM;
3969				}
3970
3971				DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3972
3973				*pp_printer = printer;
3974				result = WERR_OK;
3975
3976				break;
3977			}
3978
3979			/* no cache for this handle; see if we can match one from another handle.
3980			   Make sure to use a short lived talloc ctx */
3981
3982			if ( print_hnd )
3983				result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, sharename);
3984
3985			/* fail to disk if we don't have it with any open handle */
3986
3987			if ( !print_hnd || !W_ERROR_IS_OK(result) )
3988				result = get_a_printer_2(&printer->info_2, sharename);
3989
3990			/* we have a new printer now.  Save it with this handle */
3991
3992			if ( W_ERROR_IS_OK(result) ) {
3993				dump_a_printer(*printer, level);
3994
3995				/* save a copy in cache */
3996				if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3997					if ( !print_hnd->printer_info )
3998						print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3999
4000					if ( print_hnd->printer_info ) {
4001						/* make sure to use the handle's talloc ctx here since
4002						   the printer_2 object must last until the handle is closed */
4003
4004						print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4005
4006						/* don't fail the lookup just because the cache update failed */
4007						if ( !print_hnd->printer_info->info_2 )
4008							DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4009					}
4010				}
4011				*pp_printer = printer;
4012			}
4013			else
4014				SAFE_FREE(printer);
4015
4016			break;
4017
4018		default:
4019			result=WERR_UNKNOWN_LEVEL;
4020			break;
4021	}
4022
4023	DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4024
4025	return result;
4026}
4027
4028/****************************************************************************
4029 Deletes a NT_PRINTER_INFO_LEVEL struct.
4030****************************************************************************/
4031
4032uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4033{
4034	uint32 result;
4035	NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4036
4037	DEBUG(104,("freeing a printer at level [%d]\n", level));
4038
4039	if (printer == NULL)
4040		return 0;
4041
4042	switch (level) {
4043		case 2:
4044			if (printer->info_2 != NULL) {
4045				free_nt_printer_info_level_2(&printer->info_2);
4046				result=0;
4047			} else
4048				result=4;
4049			break;
4050
4051		default:
4052			result=1;
4053			break;
4054	}
4055
4056	SAFE_FREE(*pp_printer);
4057	return result;
4058}
4059
4060/****************************************************************************
4061****************************************************************************/
4062uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4063{
4064	uint32 result;
4065	DEBUG(104,("adding a printer at level [%d]\n", level));
4066	dump_a_printer_driver(driver, level);
4067
4068	switch (level) {
4069		case 3:
4070			result=add_a_printer_driver_3(driver.info_3);
4071			break;
4072
4073		case 6:
4074			result=add_a_printer_driver_6(driver.info_6);
4075			break;
4076
4077		default:
4078			result=1;
4079			break;
4080	}
4081
4082	return result;
4083}
4084/****************************************************************************
4085****************************************************************************/
4086
4087WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4088                            fstring drivername, const char *architecture, uint32 version)
4089{
4090	WERROR result;
4091
4092	switch (level) {
4093		case 3:
4094			/* Sometime we just want any version of the driver */
4095
4096			if ( version == DRIVER_ANY_VERSION ) {
4097				/* look for Win2k first and then for NT4 */
4098				result = get_a_printer_driver_3(&driver->info_3, drivername,
4099						architecture, 3);
4100
4101				if ( !W_ERROR_IS_OK(result) ) {
4102					result = get_a_printer_driver_3( &driver->info_3,
4103							drivername, architecture, 2 );
4104				}
4105			} else {
4106				result = get_a_printer_driver_3(&driver->info_3, drivername,
4107					architecture, version);
4108			}
4109			break;
4110
4111		default:
4112			result=W_ERROR(1);
4113			break;
4114	}
4115
4116	if (W_ERROR_IS_OK(result))
4117		dump_a_printer_driver(*driver, level);
4118
4119	return result;
4120}
4121
4122/****************************************************************************
4123****************************************************************************/
4124uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4125{
4126	uint32 result;
4127
4128	switch (level) {
4129		case 3:
4130		{
4131			NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4132			if (driver.info_3 != NULL)
4133			{
4134				info3=driver.info_3;
4135				SAFE_FREE(info3->dependentfiles);
4136				ZERO_STRUCTP(info3);
4137				SAFE_FREE(info3);
4138				result=0;
4139			} else {
4140				result=4;
4141			}
4142			break;
4143		}
4144		case 6:
4145		{
4146			NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4147			if (driver.info_6 != NULL) {
4148				info6=driver.info_6;
4149				SAFE_FREE(info6->dependentfiles);
4150				SAFE_FREE(info6->previousnames);
4151				ZERO_STRUCTP(info6);
4152				SAFE_FREE(info6);
4153				result=0;
4154			} else {
4155				result=4;
4156			}
4157			break;
4158		}
4159		default:
4160			result=1;
4161			break;
4162	}
4163	return result;
4164}
4165
4166
4167/****************************************************************************
4168  Determine whether or not a particular driver is currently assigned
4169  to a printer
4170****************************************************************************/
4171
4172BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4173{
4174	int snum;
4175	int n_services = lp_numservices();
4176	NT_PRINTER_INFO_LEVEL *printer = NULL;
4177
4178	if ( !info_3 )
4179		return False;
4180
4181	DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4182
4183	/* loop through the printers.tdb and check for the drivername */
4184
4185	for (snum=0; snum<n_services; snum++) {
4186		if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4187			continue;
4188
4189		if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4190			continue;
4191
4192		if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4193			free_a_printer( &printer, 2 );
4194			return True;
4195		}
4196
4197		free_a_printer( &printer, 2 );
4198	}
4199
4200	DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4201
4202	/* report that the driver is not in use by default */
4203
4204	return False;
4205}
4206
4207
4208/**********************************************************************
4209 Check to see if a ogiven file is in use by *info
4210 *********************************************************************/
4211
4212static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4213{
4214	int i = 0;
4215
4216	if ( !info )
4217		return False;
4218
4219	if ( strequal(file, info->driverpath) )
4220		return True;
4221
4222	if ( strequal(file, info->datafile) )
4223		return True;
4224
4225	if ( strequal(file, info->configfile) )
4226		return True;
4227
4228	if ( strequal(file, info->helpfile) )
4229		return True;
4230
4231	/* see of there are any dependent files to examine */
4232
4233	if ( !info->dependentfiles )
4234		return False;
4235
4236	while ( *info->dependentfiles[i] ) {
4237		if ( strequal(file, info->dependentfiles[i]) )
4238			return True;
4239		i++;
4240	}
4241
4242	return False;
4243
4244}
4245
4246/**********************************************************************
4247 Utility function to remove the dependent file pointed to by the
4248 input parameter from the list
4249 *********************************************************************/
4250
4251static void trim_dependent_file( fstring files[], int idx )
4252{
4253
4254	/* bump everything down a slot */
4255
4256	while( *files[idx+1] ) {
4257		fstrcpy( files[idx], files[idx+1] );
4258		idx++;
4259	}
4260
4261	*files[idx] = '\0';
4262
4263	return;
4264}
4265
4266/**********************************************************************
4267 Check if any of the files used by src are also used by drv
4268 *********************************************************************/
4269
4270static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4271				       NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4272{
4273	BOOL 	in_use = False;
4274	int 	i = 0;
4275
4276	if ( !src || !drv )
4277		return False;
4278
4279	/* check each file.  Remove it from the src structure if it overlaps */
4280
4281	if ( drv_file_in_use(src->driverpath, drv) ) {
4282		in_use = True;
4283		DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4284		fstrcpy( src->driverpath, "" );
4285	}
4286
4287	if ( drv_file_in_use(src->datafile, drv) ) {
4288		in_use = True;
4289		DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4290		fstrcpy( src->datafile, "" );
4291	}
4292
4293	if ( drv_file_in_use(src->configfile, drv) ) {
4294		in_use = True;
4295		DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4296		fstrcpy( src->configfile, "" );
4297	}
4298
4299	if ( drv_file_in_use(src->helpfile, drv) ) {
4300		in_use = True;
4301		DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4302		fstrcpy( src->helpfile, "" );
4303	}
4304
4305	/* are there any dependentfiles to examine? */
4306
4307	if ( !src->dependentfiles )
4308		return in_use;
4309
4310	while ( *src->dependentfiles[i] ) {
4311		if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4312			in_use = True;
4313			DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4314			trim_dependent_file( src->dependentfiles, i );
4315		} else
4316			i++;
4317	}
4318
4319	return in_use;
4320}
4321
4322/****************************************************************************
4323  Determine whether or not a particular driver files are currently being
4324  used by any other driver.
4325
4326  Return value is True if any files were in use by other drivers
4327  and False otherwise.
4328
4329  Upon return, *info has been modified to only contain the driver files
4330  which are not in use
4331****************************************************************************/
4332
4333BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4334{
4335	int 				i;
4336	int 				ndrivers;
4337	uint32 				version;
4338	fstring 			*list = NULL;
4339	NT_PRINTER_DRIVER_INFO_LEVEL 	driver;
4340
4341	if ( !info )
4342		return False;
4343
4344	version = info->cversion;
4345
4346	/* loop over all driver versions */
4347
4348	DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4349
4350	/* get the list of drivers */
4351
4352	list = NULL;
4353	ndrivers = get_ntdrivers(&list, info->environment, version);
4354
4355	DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4356		ndrivers, info->environment, version));
4357
4358	/* check each driver for overlap in files */
4359
4360	for (i=0; i<ndrivers; i++) {
4361		DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4362
4363		ZERO_STRUCT(driver);
4364
4365		if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4366			SAFE_FREE(list);
4367			return True;
4368		}
4369
4370		/* check if d2 uses any files from d1 */
4371		/* only if this is a different driver than the one being deleted */
4372
4373		if ( !strequal(info->name, driver.info_3->name) ) {
4374			if ( trim_overlap_drv_files(info, driver.info_3) ) {
4375				free_a_printer_driver(driver, 3);
4376				SAFE_FREE( list );
4377				return True;
4378			}
4379		}
4380
4381		free_a_printer_driver(driver, 3);
4382	}
4383
4384	SAFE_FREE(list);
4385
4386	DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4387
4388	driver.info_3 = info;
4389
4390	if ( DEBUGLEVEL >= 20 )
4391		dump_a_printer_driver( driver, 3 );
4392
4393	return False;
4394}
4395
4396/****************************************************************************
4397  Actually delete the driver files.  Make sure that
4398  printer_driver_files_in_use() return False before calling
4399  this.
4400****************************************************************************/
4401
4402static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4403{
4404	int i = 0;
4405	char *s;
4406	connection_struct *conn;
4407	DATA_BLOB null_pw;
4408	NTSTATUS nt_status;
4409	fstring res_type;
4410
4411	if ( !info_3 )
4412		return False;
4413
4414	DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4415
4416	/*
4417	 * Connect to the print$ share under the same account as the
4418	 * user connected to the rpc pipe. Note we must be root to
4419	 * do this.
4420	 */
4421
4422	null_pw = data_blob( NULL, 0 );
4423	fstrcpy(res_type, "A:");
4424	become_root();
4425        conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4426	unbecome_root();
4427
4428	if ( !conn ) {
4429		DEBUG(0,("delete_driver_files: Unable to connect\n"));
4430		return False;
4431	}
4432
4433        /* Save who we are - we are temporarily becoming the connection user. */
4434
4435	if ( !become_user(conn, conn->vuid) ) {
4436		DEBUG(0,("delete_driver_files: Can't become user!\n"));
4437		return False;
4438	}
4439
4440	/* now delete the files; must strip the '\print$' string from
4441	   fron of path                                                */
4442
4443	if ( *info_3->driverpath ) {
4444		if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4445			DEBUG(10,("deleting driverfile [%s]\n", s));
4446			unlink_internals(conn, 0, s);
4447		}
4448	}
4449
4450	if ( *info_3->configfile ) {
4451		if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4452			DEBUG(10,("deleting configfile [%s]\n", s));
4453			unlink_internals(conn, 0, s);
4454		}
4455	}
4456
4457	if ( *info_3->datafile ) {
4458		if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4459			DEBUG(10,("deleting datafile [%s]\n", s));
4460			unlink_internals(conn, 0, s);
4461		}
4462	}
4463
4464	if ( *info_3->helpfile ) {
4465		if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4466			DEBUG(10,("deleting helpfile [%s]\n", s));
4467			unlink_internals(conn, 0, s);
4468		}
4469	}
4470
4471	/* check if we are done removing files */
4472
4473	if ( info_3->dependentfiles ) {
4474		while ( *info_3->dependentfiles[i] ) {
4475			char *file;
4476
4477			/* bypass the "\print$" portion of the path */
4478
4479			if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4480				DEBUG(10,("deleting dependent file [%s]\n", file));
4481				unlink_internals(conn, 0, file );
4482			}
4483
4484			i++;
4485		}
4486	}
4487
4488	unbecome_user();
4489
4490	return True;
4491}
4492
4493/****************************************************************************
4494 Remove a printer driver from the TDB.  This assumes that the the driver was
4495 previously looked up.
4496 ***************************************************************************/
4497
4498WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4499                              uint32 version, BOOL delete_files )
4500{
4501	pstring 	key;
4502	const char     *arch;
4503	TDB_DATA 	kbuf, dbuf;
4504	NT_PRINTER_DRIVER_INFO_LEVEL	ctr;
4505
4506	/* delete the tdb data first */
4507
4508	arch = get_short_archi(info_3->environment);
4509	slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4510		arch, version, info_3->name);
4511
4512	DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4513		key, delete_files ? "TRUE" : "FALSE" ));
4514
4515	ctr.info_3 = info_3;
4516	dump_a_printer_driver( ctr, 3 );
4517
4518	kbuf.dptr=key;
4519	kbuf.dsize=strlen(key)+1;
4520
4521	/* check if the driver actually exists for this environment */
4522
4523	dbuf = tdb_fetch( tdb_drivers, kbuf );
4524	if ( !dbuf.dptr ) {
4525		DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4526		return WERR_UNKNOWN_PRINTER_DRIVER;
4527	}
4528
4529	SAFE_FREE( dbuf.dptr );
4530
4531	/* ok... the driver exists so the delete should return success */
4532
4533	if (tdb_delete(tdb_drivers, kbuf) == -1) {
4534		DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4535		return WERR_ACCESS_DENIED;
4536	}
4537
4538	/*
4539	 * now delete any associated files if delete_files == True
4540	 * even if this part failes, we return succes because the
4541	 * driver doesn not exist any more
4542	 */
4543
4544	if ( delete_files )
4545		delete_driver_files( info_3, user );
4546
4547
4548	DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4549
4550	return WERR_OK;
4551	}
4552
4553/****************************************************************************
4554 Store a security desc for a printer.
4555****************************************************************************/
4556
4557WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4558{
4559	SEC_DESC_BUF *new_secdesc_ctr = NULL;
4560	SEC_DESC_BUF *old_secdesc_ctr = NULL;
4561	prs_struct ps;
4562	TALLOC_CTX *mem_ctx = NULL;
4563	fstring key;
4564	WERROR status;
4565
4566	mem_ctx = talloc_init("nt_printing_setsec");
4567	if (mem_ctx == NULL)
4568		return WERR_NOMEM;
4569
4570        /* The old owner and group sids of the security descriptor are not
4571	   present when new ACEs are added or removed by changing printer
4572	   permissions through NT.  If they are NULL in the new security
4573	   descriptor then copy them over from the old one. */
4574
4575	if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4576		DOM_SID *owner_sid, *group_sid;
4577		SEC_ACL *dacl, *sacl;
4578		SEC_DESC *psd = NULL;
4579		size_t size;
4580
4581		nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4582
4583		/* Pick out correct owner and group sids */
4584
4585		owner_sid = secdesc_ctr->sec->owner_sid ?
4586			secdesc_ctr->sec->owner_sid :
4587			old_secdesc_ctr->sec->owner_sid;
4588
4589		group_sid = secdesc_ctr->sec->grp_sid ?
4590			secdesc_ctr->sec->grp_sid :
4591			old_secdesc_ctr->sec->grp_sid;
4592
4593		dacl = secdesc_ctr->sec->dacl ?
4594			secdesc_ctr->sec->dacl :
4595			old_secdesc_ctr->sec->dacl;
4596
4597		sacl = secdesc_ctr->sec->sacl ?
4598			secdesc_ctr->sec->sacl :
4599			old_secdesc_ctr->sec->sacl;
4600
4601		/* Make a deep copy of the security descriptor */
4602
4603		psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4604				    owner_sid, group_sid,
4605				    sacl,
4606				    dacl,
4607				    &size);
4608
4609		new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4610	}
4611
4612	if (!new_secdesc_ctr) {
4613		new_secdesc_ctr = secdesc_ctr;
4614	}
4615
4616	/* Store the security descriptor in a tdb */
4617
4618	prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4619		 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4620
4621	if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4622			     &ps, 1)) {
4623		status = WERR_BADFUNC;
4624		goto out;
4625	}
4626
4627	slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4628
4629	if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4630		status = WERR_OK;
4631	} else {
4632		DEBUG(1,("Failed to store secdesc for %s\n", printername));
4633		status = WERR_BADFUNC;
4634	}
4635
4636	/* Free malloc'ed memory */
4637
4638 out:
4639
4640	prs_mem_free(&ps);
4641	if (mem_ctx)
4642		talloc_destroy(mem_ctx);
4643	return status;
4644}
4645
4646/****************************************************************************
4647 Construct a default security descriptor buffer for a printer.
4648****************************************************************************/
4649
4650static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4651{
4652	SEC_ACE ace[3];
4653	SEC_ACCESS sa;
4654	SEC_ACL *psa = NULL;
4655	SEC_DESC_BUF *sdb = NULL;
4656	SEC_DESC *psd = NULL;
4657	DOM_SID owner_sid;
4658	size_t sd_size;
4659
4660	/* Create an ACE where Everyone is allowed to print */
4661
4662	init_sec_access(&sa, PRINTER_ACE_PRINT);
4663	init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4664		     sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4665
4666	/* Make the security descriptor owned by the Administrators group
4667	   on the PDC of the domain. */
4668
4669	if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4670		sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4671	} else {
4672
4673		/* Backup plan - make printer owned by admins.
4674 		   This should emulate a lanman printer as security
4675 		   settings can't be changed. */
4676
4677		sid_copy(&owner_sid, get_global_sam_sid());
4678		sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4679	}
4680
4681	init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4682	init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4683		     sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4684		     SEC_ACE_FLAG_INHERIT_ONLY);
4685
4686	init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4687	init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4688		     sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4689
4690	/* The ACL revision number in rpc_secdesc.h differs from the one
4691	   created by NT when setting ACE entries in printer
4692	   descriptors.  NT4 complains about the property being edited by a
4693	   NT5 machine. */
4694
4695	if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4696		psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4697				    &owner_sid, NULL,
4698				    NULL, psa, &sd_size);
4699	}
4700
4701	if (!psd) {
4702		DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4703		return NULL;
4704	}
4705
4706	sdb = make_sec_desc_buf(ctx, sd_size, psd);
4707
4708	DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4709		 (unsigned int)sd_size));
4710
4711	return sdb;
4712}
4713
4714/****************************************************************************
4715 Get a security desc for a printer.
4716****************************************************************************/
4717
4718BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4719{
4720	prs_struct ps;
4721	fstring key;
4722	char *temp;
4723
4724	if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4725		printername = temp + 1;
4726	}
4727
4728	/* Fetch security descriptor from tdb */
4729
4730	slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4731
4732	if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4733	    !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4734
4735		DEBUG(4,("using default secdesc for %s\n", printername));
4736
4737		if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4738			return False;
4739		}
4740
4741		/* Save default security descriptor for later */
4742
4743		prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4744				sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4745
4746		if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4747			tdb_prs_store(tdb_printers, key, &ps);
4748
4749		prs_mem_free(&ps);
4750
4751		return True;
4752	}
4753
4754	/* If security descriptor is owned by S-1-1-0 and winbindd is up,
4755	   this security descriptor has been created when winbindd was
4756	   down.  Take ownership of security descriptor. */
4757
4758	if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4759		DOM_SID owner_sid;
4760
4761		/* Change sd owner to workgroup administrator */
4762
4763		if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4764			SEC_DESC_BUF *new_secdesc_ctr = NULL;
4765			SEC_DESC *psd = NULL;
4766			size_t size;
4767
4768			/* Create new sd */
4769
4770			sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4771
4772			psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4773					    &owner_sid,
4774					    (*secdesc_ctr)->sec->grp_sid,
4775					    (*secdesc_ctr)->sec->sacl,
4776					    (*secdesc_ctr)->sec->dacl,
4777					    &size);
4778
4779			new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4780
4781			/* Swap with other one */
4782
4783			*secdesc_ctr = new_secdesc_ctr;
4784
4785			/* Set it */
4786
4787			nt_printing_setsec(printername, *secdesc_ctr);
4788		}
4789	}
4790
4791	if (DEBUGLEVEL >= 10) {
4792		SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4793		int i;
4794
4795		DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4796			   printername, the_acl->num_aces));
4797
4798		for (i = 0; i < the_acl->num_aces; i++) {
4799			fstring sid_str;
4800
4801			sid_to_string(sid_str, &the_acl->ace[i].trustee);
4802
4803			DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4804				   the_acl->ace[i].type, the_acl->ace[i].flags,
4805				   the_acl->ace[i].info.mask));
4806		}
4807	}
4808
4809	prs_mem_free(&ps);
4810	return True;
4811}
4812
4813/* error code:
4814	0: everything OK
4815	1: level not implemented
4816	2: file doesn't exist
4817	3: can't allocate memory
4818	4: can't free memory
4819	5: non existant struct
4820*/
4821
4822/*
4823	A printer and a printer driver are 2 different things.
4824	NT manages them separatelly, Samba does the same.
4825	Why ? Simply because it's easier and it makes sense !
4826
4827	Now explanation: You have 3 printers behind your samba server,
4828	2 of them are the same make and model (laser A and B). But laser B
4829	has an 3000 sheet feeder and laser A doesn't such an option.
4830	Your third printer is an old dot-matrix model for the accounting :-).
4831
4832	If the /usr/local/samba/lib directory (default dir), you will have
4833	5 files to describe all of this.
4834
4835	3 files for the printers (1 by printer):
4836		NTprinter_laser A
4837		NTprinter_laser B
4838		NTprinter_accounting
4839	2 files for the drivers (1 for the laser and 1 for the dot matrix)
4840		NTdriver_printer model X
4841		NTdriver_printer model Y
4842
4843jfm: I should use this comment for the text file to explain
4844	same thing for the forms BTW.
4845	Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4846
4847*/
4848
4849/* Convert generic access rights to printer object specific access rights.
4850   It turns out that NT4 security descriptors use generic access rights and
4851   NT5 the object specific ones. */
4852
4853void map_printer_permissions(SEC_DESC *sd)
4854{
4855	int i;
4856
4857	for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4858		se_map_generic(&sd->dacl->ace[i].info.mask,
4859			       &printer_generic_mapping);
4860	}
4861}
4862
4863/****************************************************************************
4864 Check a user has permissions to perform the given operation.  We use the
4865 permission constants defined in include/rpc_spoolss.h to check the various
4866 actions we perform when checking printer access.
4867
4868   PRINTER_ACCESS_ADMINISTER:
4869       print_queue_pause, print_queue_resume, update_printer_sec,
4870       update_printer, spoolss_addprinterex_level_2,
4871       _spoolss_setprinterdata
4872
4873   PRINTER_ACCESS_USE:
4874       print_job_start
4875
4876   JOB_ACCESS_ADMINISTER:
4877       print_job_delete, print_job_pause, print_job_resume,
4878       print_queue_purge
4879
4880 ****************************************************************************/
4881BOOL print_access_check(struct current_user *user, int snum, int access_type)
4882{
4883	SEC_DESC_BUF *secdesc = NULL;
4884	uint32 access_granted;
4885	NTSTATUS status;
4886	BOOL result;
4887	const char *pname;
4888	TALLOC_CTX *mem_ctx = NULL;
4889	extern struct current_user current_user;
4890
4891	/* If user is NULL then use the current_user structure */
4892
4893	if (!user)
4894		user = &current_user;
4895
4896	/* Always allow root or printer admins to do anything */
4897
4898	if (user->uid == 0 ||
4899	    user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4900		return True;
4901	}
4902
4903	/* Get printer name */
4904
4905	pname = PRINTERNAME(snum);
4906
4907	if (!pname || !*pname) {
4908		errno = EACCES;
4909		return False;
4910	}
4911
4912	/* Get printer security descriptor */
4913
4914	if(!(mem_ctx = talloc_init("print_access_check"))) {
4915		errno = ENOMEM;
4916		return False;
4917	}
4918
4919	nt_printing_getsec(mem_ctx, pname, &secdesc);
4920
4921	if (access_type == JOB_ACCESS_ADMINISTER) {
4922		SEC_DESC_BUF *parent_secdesc = secdesc;
4923
4924		/* Create a child security descriptor to check permissions
4925		   against.  This is because print jobs are child objects
4926		   objects of a printer. */
4927
4928		secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4929
4930		/* Now this is the bit that really confuses me.  The access
4931		   type needs to be changed from JOB_ACCESS_ADMINISTER to
4932		   PRINTER_ACCESS_ADMINISTER for this to work.  Something
4933		   to do with the child (job) object becoming like a
4934		   printer??  -tpot */
4935
4936		access_type = PRINTER_ACCESS_ADMINISTER;
4937	}
4938
4939	/* Check access */
4940
4941	map_printer_permissions(secdesc->sec);
4942
4943	result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4944				 &access_granted, &status);
4945
4946	DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4947
4948	talloc_destroy(mem_ctx);
4949
4950	if (!result)
4951		errno = EACCES;
4952
4953	return result;
4954}
4955
4956/****************************************************************************
4957 Check the time parameters allow a print operation.
4958*****************************************************************************/
4959
4960BOOL print_time_access_check(int snum)
4961{
4962	NT_PRINTER_INFO_LEVEL *printer = NULL;
4963	BOOL ok = False;
4964	time_t now = time(NULL);
4965	struct tm *t;
4966	uint32 mins;
4967
4968	if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4969		return False;
4970
4971	if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4972		ok = True;
4973
4974	t = gmtime(&now);
4975	mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4976
4977	if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4978		ok = True;
4979
4980	free_a_printer(&printer, 2);
4981
4982	if (!ok)
4983		errno = EACCES;
4984
4985	return ok;
4986}
4987
4988