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