source: vendor/3.5.10/source3/printing/nt_printing.c

Last change on this file was 597, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update vendor to version 3.5.9

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