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

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

Samba 3.5: Update vendor to version 3.5.8

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