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