r14489: Guard against coverity reversion. #181 is a false positive
[Samba/nascimento.git] / source3 / printing / nt_printing.c
blob63f722c9b59c0fcabde0228b8e236b64158ca216
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.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern struct current_user current_user;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 STANDARD_MAPPING printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 STANDARD_MAPPING printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 struct table_node {
202 const char *long_archi;
203 const char *short_archi;
204 int version;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
212 #define SPL_ARCH_IA64 "IA64"
213 #define SPL_ARCH_X64 "x64"
215 static const struct table_node archi_table[]= {
217 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
218 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
219 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
220 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
221 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
222 {"Windows IA64", SPL_ARCH_IA64, 3 },
223 {"Windows x64", SPL_ARCH_X64, 3 },
224 {NULL, "", -1 }
228 /****************************************************************************
229 generate a new TDB_DATA key for storing a printer
230 ****************************************************************************/
232 static TDB_DATA make_printer_tdbkey( const char *sharename )
234 fstring share;
235 static pstring keystr;
236 TDB_DATA key;
238 fstrcpy( share, sharename );
239 strlower_m( share );
241 pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
243 key.dptr = keystr;
244 key.dsize = strlen(keystr)+1;
246 return key;
249 /****************************************************************************
250 generate a new TDB_DATA key for storing a printer security descriptor
251 ****************************************************************************/
253 static char* make_printers_secdesc_tdbkey( const char* sharename )
255 fstring share;
256 static pstring keystr;
258 fstrcpy( share, sharename );
259 strlower_m( share );
261 pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
263 return keystr;
266 /****************************************************************************
267 ****************************************************************************/
269 static BOOL upgrade_to_version_3(void)
271 TDB_DATA kbuf, newkey, dbuf;
273 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
275 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
278 dbuf = tdb_fetch(tdb_drivers, kbuf);
280 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281 DEBUG(0,("upgrade_to_version_3:moving form\n"));
282 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
285 return False;
287 if (tdb_delete(tdb_drivers, kbuf) != 0) {
288 SAFE_FREE(dbuf.dptr);
289 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
290 return False;
294 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
299 return False;
301 if (tdb_delete(tdb_drivers, kbuf) != 0) {
302 SAFE_FREE(dbuf.dptr);
303 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
304 return False;
308 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
313 return False;
315 if (tdb_delete(tdb_drivers, kbuf) != 0) {
316 SAFE_FREE(dbuf.dptr);
317 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
318 return False;
322 SAFE_FREE(dbuf.dptr);
325 return True;
328 /*******************************************************************
329 Fix an issue with security descriptors. Printer sec_desc must
330 use more than the generic bits that were previously used
331 in <= 3.0.14a. They must also have a owner and group SID assigned.
332 Otherwise, any printers than have been migrated to a Windows
333 host using printmig.exe will not be accessible.
334 *******************************************************************/
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337 TDB_DATA data, void *state )
339 prs_struct ps;
340 SEC_DESC_BUF *sd_orig = NULL;
341 SEC_DESC_BUF *sd_new, *sd_store;
342 SEC_DESC *sec, *new_sec;
343 TALLOC_CTX *ctx = state;
344 int result, i;
345 uint32 sd_size;
346 size_t size_new_sec;
347 DOM_SID sid;
349 if (!data.dptr || data.dsize == 0)
350 return 0;
352 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
353 return 0;
355 /* upgrade the security descriptor */
357 ZERO_STRUCT( ps );
359 prs_init( &ps, 0, ctx, UNMARSHALL );
360 prs_give_memory( &ps, data.dptr, data.dsize, True );
362 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
363 /* delete bad entries */
364 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
365 tdb_delete( tdb_printers, key );
366 return 0;
369 sec = sd_orig->sec;
371 /* is this even valid? */
373 if ( !sec->dacl )
374 return 0;
376 /* update access masks */
378 for ( i=0; i<sec->dacl->num_aces; i++ ) {
379 switch ( sec->dacl->ace[i].info.mask ) {
380 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
381 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
382 break;
384 case GENERIC_ALL_ACCESS:
385 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
386 break;
388 case READ_CONTROL_ACCESS:
389 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
391 default: /* no change */
392 break;
396 /* create a new SEC_DESC with the appropriate owner and group SIDs */
398 string_to_sid(&sid, "S-1-5-32-544" );
399 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
400 &sid, &sid,
401 NULL, NULL, &size_new_sec );
402 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
404 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
405 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
406 return 0;
409 /* store it back */
411 sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
412 prs_init(&ps, sd_size, ctx, MARSHALL);
414 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
415 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
416 return 0;
419 data.dptr = prs_data_p( &ps );
420 data.dsize = sd_size;
422 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
424 prs_mem_free( &ps );
426 /* 0 to continue and non-zero to stop traversal */
428 return (result == -1);
431 /*******************************************************************
432 *******************************************************************/
434 static BOOL upgrade_to_version_4(void)
436 TALLOC_CTX *ctx;
437 int result;
439 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
441 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
442 return False;
444 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
446 talloc_destroy( ctx );
448 return ( result != -1 );
451 /*******************************************************************
452 Fix an issue with security descriptors. Printer sec_desc must
453 use more than the generic bits that were previously used
454 in <= 3.0.14a. They must also have a owner and group SID assigned.
455 Otherwise, any printers than have been migrated to a Windows
456 host using printmig.exe will not be accessible.
457 *******************************************************************/
459 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
460 TDB_DATA data, void *state )
462 TDB_DATA new_key;
464 if (!data.dptr || data.dsize == 0)
465 return 0;
467 /* upgrade printer records and security descriptors */
469 if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
472 else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473 new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) );
474 new_key.dsize = strlen( new_key.dptr ) + 1;
476 else {
477 /* ignore this record */
478 return 0;
481 /* delete the original record and store under the normalized key */
483 if ( tdb_delete( the_tdb, key ) != 0 ) {
484 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
485 key.dptr));
486 return 1;
489 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
490 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
491 key.dptr));
492 return 1;
495 return 0;
498 /*******************************************************************
499 *******************************************************************/
501 static BOOL upgrade_to_version_5(void)
503 TALLOC_CTX *ctx;
504 int result;
506 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
508 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
509 return False;
511 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
513 talloc_destroy( ctx );
515 return ( result != -1 );
518 /****************************************************************************
519 Open the NT printing tdbs. Done once before fork().
520 ****************************************************************************/
522 BOOL nt_printing_init(void)
524 const char *vstring = "INFO/version";
525 WERROR win_rc;
526 int32 vers_id;
528 if ( tdb_drivers && tdb_printers && tdb_forms )
529 return True;
531 if (tdb_drivers)
532 tdb_close(tdb_drivers);
533 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
534 if (!tdb_drivers) {
535 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
536 lock_path("ntdrivers.tdb"), strerror(errno) ));
537 return False;
540 if (tdb_printers)
541 tdb_close(tdb_printers);
542 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
543 if (!tdb_printers) {
544 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
545 lock_path("ntprinters.tdb"), strerror(errno) ));
546 return False;
549 if (tdb_forms)
550 tdb_close(tdb_forms);
551 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
552 if (!tdb_forms) {
553 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
554 lock_path("ntforms.tdb"), strerror(errno) ));
555 return False;
558 /* handle a Samba upgrade */
560 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
561 if (vers_id == -1) {
562 DEBUG(10, ("Fresh database\n"));
563 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
564 vers_id = NTDRIVERS_DATABASE_VERSION_5;
567 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
569 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
570 if (!upgrade_to_version_3())
571 return False;
572 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
573 vers_id = NTDRIVERS_DATABASE_VERSION_3;
576 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
577 /* Written on a bigendian machine with old fetch_int code. Save as le. */
578 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
579 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
580 vers_id = NTDRIVERS_DATABASE_VERSION_3;
583 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
584 if ( !upgrade_to_version_4() )
585 return False;
586 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
587 vers_id = NTDRIVERS_DATABASE_VERSION_4;
590 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
591 if ( !upgrade_to_version_5() )
592 return False;
593 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
594 vers_id = NTDRIVERS_DATABASE_VERSION_5;
598 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
599 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
600 return False;
604 update_c_setprinter(True);
607 * register callback to handle updating printers as new
608 * drivers are installed
611 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
614 * register callback to handle updating printer data
615 * when a driver is initialized
618 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
620 /* of course, none of the message callbacks matter if you don't
621 tell messages.c that you interested in receiving PRINT_GENERAL
622 msgs. This is done in claim_connection() */
625 if ( lp_security() == SEC_ADS ) {
626 win_rc = check_published_printers();
627 if (!W_ERROR_IS_OK(win_rc))
628 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
631 return True;
634 /*******************************************************************
635 Function to allow filename parsing "the old way".
636 ********************************************************************/
638 static BOOL driver_unix_convert(char *name,connection_struct *conn,
639 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
641 unix_format(name);
642 unix_clean_name(name);
643 trim_string(name,"/","/");
644 return unix_convert(name, conn, saved_last_component, bad_path, pst);
647 /*******************************************************************
648 tdb traversal function for counting printers.
649 ********************************************************************/
651 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
652 TDB_DATA data, void *context)
654 int *printer_count = (int*)context;
656 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
657 (*printer_count)++;
658 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
661 return 0;
664 /*******************************************************************
665 Update the spooler global c_setprinter. This variable is initialized
666 when the parent smbd starts with the number of existing printers. It
667 is monotonically increased by the current number of printers *after*
668 each add or delete printer RPC. Only Microsoft knows why... JRR020119
669 ********************************************************************/
671 uint32 update_c_setprinter(BOOL initialize)
673 int32 c_setprinter;
674 int32 printer_count = 0;
676 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
678 /* Traverse the tdb, counting the printers */
679 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
681 /* If initializing, set c_setprinter to current printers count
682 * otherwise, bump it by the current printer count
684 if (!initialize)
685 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
686 else
687 c_setprinter = printer_count;
689 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
690 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
692 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
694 return (uint32)c_setprinter;
697 /*******************************************************************
698 Get the spooler global c_setprinter, accounting for initialization.
699 ********************************************************************/
701 uint32 get_c_setprinter(void)
703 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
705 if (c_setprinter == (int32)-1)
706 c_setprinter = update_c_setprinter(True);
708 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
710 return (uint32)c_setprinter;
713 /****************************************************************************
714 Get builtin form struct list.
715 ****************************************************************************/
717 int get_builtin_ntforms(nt_forms_struct **list)
719 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
720 return sizeof(default_forms) / sizeof(default_forms[0]);
723 /****************************************************************************
724 get a builtin form struct
725 ****************************************************************************/
727 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
729 int i,count;
730 fstring form_name;
731 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
732 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
733 count = sizeof(default_forms) / sizeof(default_forms[0]);
734 for (i=0;i<count;i++) {
735 if (strequal(form_name,default_forms[i].name)) {
736 DEBUGADD(6,("Found builtin form %s \n", form_name));
737 memcpy(form,&default_forms[i],sizeof(*form));
738 break;
742 return (i !=count);
745 /****************************************************************************
746 get a form struct list.
747 ****************************************************************************/
749 int get_ntforms(nt_forms_struct **list)
751 TDB_DATA kbuf, newkey, dbuf;
752 nt_forms_struct form;
753 int ret;
754 int i;
755 int n = 0;
757 *list = NULL;
759 for (kbuf = tdb_firstkey(tdb_forms);
760 kbuf.dptr;
761 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
763 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
764 continue;
766 dbuf = tdb_fetch(tdb_forms, kbuf);
767 if (!dbuf.dptr)
768 continue;
770 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
771 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
772 &i, &form.flag, &form.width, &form.length, &form.left,
773 &form.top, &form.right, &form.bottom);
774 SAFE_FREE(dbuf.dptr);
775 if (ret != dbuf.dsize)
776 continue;
778 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
779 if (!*list) {
780 DEBUG(0,("get_ntforms: Realloc fail.\n"));
781 return 0;
783 (*list)[n] = form;
784 n++;
788 return n;
791 /****************************************************************************
792 write a form struct list
793 ****************************************************************************/
794 int write_ntforms(nt_forms_struct **list, int number)
796 pstring buf, key;
797 int len;
798 TDB_DATA kbuf,dbuf;
799 int i;
801 for (i=0;i<number;i++) {
802 /* save index, so list is rebuilt in correct order */
803 len = tdb_pack(buf, sizeof(buf), "dddddddd",
804 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
805 (*list)[i].left, (*list)[i].top, (*list)[i].right,
806 (*list)[i].bottom);
807 if (len > sizeof(buf)) break;
808 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
809 kbuf.dsize = strlen(key)+1;
810 kbuf.dptr = key;
811 dbuf.dsize = len;
812 dbuf.dptr = buf;
813 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
816 return i;
819 /****************************************************************************
820 add a form struct at the end of the list
821 ****************************************************************************/
822 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
824 int n=0;
825 BOOL update;
826 fstring form_name;
829 * NT tries to add forms even when
830 * they are already in the base
831 * only update the values if already present
834 update=False;
836 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
837 for (n=0; n<*count; n++) {
838 if ( strequal((*list)[n].name, form_name) ) {
839 update=True;
840 break;
844 if (update==False) {
845 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
846 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
847 return False;
849 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
850 (*count)++;
853 (*list)[n].flag=form->flags;
854 (*list)[n].width=form->size_x;
855 (*list)[n].length=form->size_y;
856 (*list)[n].left=form->left;
857 (*list)[n].top=form->top;
858 (*list)[n].right=form->right;
859 (*list)[n].bottom=form->bottom;
861 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
862 update ? "updated" : "added", form_name));
864 return True;
867 /****************************************************************************
868 Delete a named form struct.
869 ****************************************************************************/
871 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
873 pstring key;
874 TDB_DATA kbuf;
875 int n=0;
876 fstring form_name;
878 *ret = WERR_OK;
880 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
882 for (n=0; n<*count; n++) {
883 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
884 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
885 break;
889 if (n == *count) {
890 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
891 *ret = WERR_INVALID_PARAM;
892 return False;
895 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
896 kbuf.dsize = strlen(key)+1;
897 kbuf.dptr = key;
898 if (tdb_delete(tdb_forms, kbuf) != 0) {
899 *ret = WERR_NOMEM;
900 return False;
903 return True;
906 /****************************************************************************
907 Update a form struct.
908 ****************************************************************************/
910 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
912 int n=0;
913 fstring form_name;
914 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
916 DEBUG(106, ("[%s]\n", form_name));
917 for (n=0; n<count; n++) {
918 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
919 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
920 break;
923 if (n==count) return;
925 (*list)[n].flag=form->flags;
926 (*list)[n].width=form->size_x;
927 (*list)[n].length=form->size_y;
928 (*list)[n].left=form->left;
929 (*list)[n].top=form->top;
930 (*list)[n].right=form->right;
931 (*list)[n].bottom=form->bottom;
934 /****************************************************************************
935 Get the nt drivers list.
936 Traverse the database and look-up the matching names.
937 ****************************************************************************/
938 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
940 int total=0;
941 const char *short_archi;
942 pstring key;
943 TDB_DATA kbuf, newkey;
945 short_archi = get_short_archi(architecture);
946 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
948 for (kbuf = tdb_firstkey(tdb_drivers);
949 kbuf.dptr;
950 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
952 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
953 continue;
955 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
956 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
957 return -1;
960 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
961 total++;
964 return(total);
967 /****************************************************************************
968 function to do the mapping between the long architecture name and
969 the short one.
970 ****************************************************************************/
971 const char *get_short_archi(const char *long_archi)
973 int i=-1;
975 DEBUG(107,("Getting architecture dependant directory\n"));
976 do {
977 i++;
978 } while ( (archi_table[i].long_archi!=NULL ) &&
979 StrCaseCmp(long_archi, archi_table[i].long_archi) );
981 if (archi_table[i].long_archi==NULL) {
982 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
983 return NULL;
986 /* this might be client code - but shouldn't this be an fstrcpy etc? */
989 DEBUGADD(108,("index: [%d]\n", i));
990 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
991 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
993 return archi_table[i].short_archi;
996 /****************************************************************************
997 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
998 There are two case to be covered here: PE (Portable Executable) and NE (New
999 Executable) files. Both files support the same INFO structure, but PE files
1000 store the signature in unicode, and NE files store it as !unicode.
1001 returns -1 on error, 1 on version info found, and 0 on no version info found.
1002 ****************************************************************************/
1004 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1006 int i;
1007 char *buf = NULL;
1008 ssize_t byte_count;
1010 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1011 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1012 fname, PE_HEADER_SIZE));
1013 goto error_exit;
1016 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1017 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1018 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1019 fname, (unsigned long)byte_count));
1020 goto no_version_info;
1023 /* Is this really a DOS header? */
1024 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1025 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1026 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1027 goto no_version_info;
1030 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1031 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1032 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1033 fname, errno));
1034 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1035 goto no_version_info;
1038 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1039 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1040 fname, (unsigned long)byte_count));
1041 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1042 goto no_version_info;
1045 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1046 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1047 unsigned int num_sections;
1048 unsigned int section_table_bytes;
1050 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1051 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1052 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1053 /* At this point, we assume the file is in error. It still could be somthing
1054 * else besides a PE file, but it unlikely at this point.
1056 goto error_exit;
1059 /* get the section table */
1060 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1061 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1062 if (section_table_bytes == 0)
1063 goto error_exit;
1065 SAFE_FREE(buf);
1066 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
1067 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1068 fname, section_table_bytes));
1069 goto error_exit;
1072 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1073 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1074 fname, (unsigned long)byte_count));
1075 goto error_exit;
1078 /* Iterate the section table looking for the resource section ".rsrc" */
1079 for (i = 0; i < num_sections; i++) {
1080 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1082 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1083 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1084 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1086 if (section_bytes == 0)
1087 goto error_exit;
1089 SAFE_FREE(buf);
1090 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
1091 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1092 fname, section_bytes));
1093 goto error_exit;
1096 /* Seek to the start of the .rsrc section info */
1097 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1098 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1099 fname, errno));
1100 goto error_exit;
1103 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1104 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1105 fname, (unsigned long)byte_count));
1106 goto error_exit;
1109 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1110 goto error_exit;
1112 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1113 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1114 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1115 /* Align to next long address */
1116 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1118 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1119 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1120 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1122 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1123 fname, *major, *minor,
1124 (*major>>16)&0xffff, *major&0xffff,
1125 (*minor>>16)&0xffff, *minor&0xffff));
1126 SAFE_FREE(buf);
1127 return 1;
1134 /* Version info not found, fall back to origin date/time */
1135 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1136 SAFE_FREE(buf);
1137 return 0;
1139 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1140 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1141 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1142 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1143 /* At this point, we assume the file is in error. It still could be somthing
1144 * else besides a NE file, but it unlikely at this point. */
1145 goto error_exit;
1148 /* Allocate a bit more space to speed up things */
1149 SAFE_FREE(buf);
1150 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1151 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1152 fname, PE_HEADER_SIZE));
1153 goto error_exit;
1156 /* This is a HACK! I got tired of trying to sort through the messy
1157 * 'NE' file format. If anyone wants to clean this up please have at
1158 * it, but this works. 'NE' files will eventually fade away. JRR */
1159 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1160 /* Cover case that should not occur in a well formed 'NE' .dll file */
1161 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1163 for(i=0; i<byte_count; i++) {
1164 /* Fast skip past data that can't possibly match */
1165 if (buf[i] != 'V') continue;
1167 /* Potential match data crosses buf boundry, move it to beginning
1168 * of buf, and fill the buf with as much as it will hold. */
1169 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1170 int bc;
1172 memcpy(buf, &buf[i], byte_count-i);
1173 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1174 (byte_count-i))) < 0) {
1176 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1177 fname, errno));
1178 goto error_exit;
1181 byte_count = bc + (byte_count - i);
1182 if (byte_count<VS_VERSION_INFO_SIZE) break;
1184 i = 0;
1187 /* Check that the full signature string and the magic number that
1188 * follows exist (not a perfect solution, but the chances that this
1189 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1190 * twice, as it is simpler to read the code. */
1191 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1192 /* Compute skip alignment to next long address */
1193 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1194 sizeof(VS_SIGNATURE)) & 3;
1195 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1197 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1198 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1199 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1200 fname, *major, *minor,
1201 (*major>>16)&0xffff, *major&0xffff,
1202 (*minor>>16)&0xffff, *minor&0xffff));
1203 SAFE_FREE(buf);
1204 return 1;
1209 /* Version info not found, fall back to origin date/time */
1210 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1211 SAFE_FREE(buf);
1212 return 0;
1214 } else
1215 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1216 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1217 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1219 no_version_info:
1220 SAFE_FREE(buf);
1221 return 0;
1223 error_exit:
1224 SAFE_FREE(buf);
1225 return -1;
1228 /****************************************************************************
1229 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1230 share one or more files. During the MS installation process files are checked
1231 to insure that only a newer version of a shared file is installed over an
1232 older version. There are several possibilities for this comparison. If there
1233 is no previous version, the new one is newer (obviously). If either file is
1234 missing the version info structure, compare the creation date (on Unix use
1235 the modification date). Otherwise chose the numerically larger version number.
1236 ****************************************************************************/
1238 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1240 BOOL use_version = True;
1241 pstring filepath;
1243 uint32 new_major;
1244 uint32 new_minor;
1245 time_t new_create_time;
1247 uint32 old_major;
1248 uint32 old_minor;
1249 time_t old_create_time;
1251 files_struct *fsp = NULL;
1252 SMB_STRUCT_STAT st;
1253 SMB_STRUCT_STAT stat_buf;
1254 BOOL bad_path;
1256 SET_STAT_INVALID(st);
1257 SET_STAT_INVALID(stat_buf);
1258 new_create_time = (time_t)0;
1259 old_create_time = (time_t)0;
1261 /* Get file version info (if available) for previous file (if it exists) */
1262 pstrcpy(filepath, old_file);
1264 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1266 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1267 FILE_GENERIC_READ,
1268 FILE_SHARE_READ|FILE_SHARE_WRITE,
1269 FILE_OPEN,
1271 FILE_ATTRIBUTE_NORMAL,
1272 INTERNAL_OPEN_ONLY,
1273 NULL);
1275 if (!fsp) {
1276 /* Old file not found, so by definition new file is in fact newer */
1277 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1278 filepath, errno));
1279 return True;
1281 } else {
1282 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1283 if (ret == -1) {
1284 goto error_exit;
1287 if (!ret) {
1288 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1289 old_file));
1290 use_version = False;
1291 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1292 old_create_time = st.st_mtime;
1293 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1296 close_file(fsp, NORMAL_CLOSE);
1298 /* Get file version info (if available) for new file */
1299 pstrcpy(filepath, new_file);
1300 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1302 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1303 FILE_GENERIC_READ,
1304 FILE_SHARE_READ|FILE_SHARE_WRITE,
1305 FILE_OPEN,
1307 FILE_ATTRIBUTE_NORMAL,
1308 INTERNAL_OPEN_ONLY,
1309 NULL);
1311 if (!fsp) {
1312 /* New file not found, this shouldn't occur if the caller did its job */
1313 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1314 filepath, errno));
1315 goto error_exit;
1317 } else {
1318 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1319 if (ret == -1) {
1320 goto error_exit;
1323 if (!ret) {
1324 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1325 new_file));
1326 use_version = False;
1327 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1328 new_create_time = st.st_mtime;
1329 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1332 close_file(fsp, NORMAL_CLOSE);
1334 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1335 /* Compare versions and choose the larger version number */
1336 if (new_major > old_major ||
1337 (new_major == old_major && new_minor > old_minor)) {
1339 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1340 return True;
1342 else {
1343 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1344 return False;
1347 } else {
1348 /* Compare modification time/dates and choose the newest time/date */
1349 if (new_create_time > old_create_time) {
1350 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1351 return True;
1353 else {
1354 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1355 return False;
1359 error_exit:
1360 if(fsp)
1361 close_file(fsp, NORMAL_CLOSE);
1362 return -1;
1365 /****************************************************************************
1366 Determine the correct cVersion associated with an architecture and driver
1367 ****************************************************************************/
1368 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1369 struct current_user *user, WERROR *perr)
1371 int cversion;
1372 NTSTATUS nt_status;
1373 pstring driverpath;
1374 DATA_BLOB null_pw;
1375 fstring res_type;
1376 files_struct *fsp = NULL;
1377 BOOL bad_path;
1378 SMB_STRUCT_STAT st;
1379 connection_struct *conn;
1381 SET_STAT_INVALID(st);
1383 *perr = WERR_INVALID_PARAM;
1385 /* If architecture is Windows 95/98/ME, the version is always 0. */
1386 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1387 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1388 *perr = WERR_OK;
1389 return 0;
1392 /* If architecture is Windows x64, the version is always 3. */
1393 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1394 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1395 *perr = WERR_OK;
1396 return 3;
1400 * Connect to the print$ share under the same account as the user connected
1401 * to the rpc pipe. Note we must still be root to do this.
1404 /* Null password is ok - we are already an authenticated user... */
1405 null_pw = data_blob(NULL, 0);
1406 fstrcpy(res_type, "A:");
1407 become_root();
1408 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1409 unbecome_root();
1411 if (conn == NULL) {
1412 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1413 *perr = ntstatus_to_werror(nt_status);
1414 return -1;
1417 /* We are temporarily becoming the connection user. */
1418 if (!become_user(conn, user->vuid)) {
1419 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1420 *perr = WERR_ACCESS_DENIED;
1421 return -1;
1424 /* Open the driver file (Portable Executable format) and determine the
1425 * deriver the cversion. */
1426 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1428 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1430 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1431 *perr = WERR_BADFILE;
1432 goto error_exit;
1435 fsp = open_file_ntcreate(conn, driverpath, &st,
1436 FILE_GENERIC_READ,
1437 FILE_SHARE_READ|FILE_SHARE_WRITE,
1438 FILE_OPEN,
1440 FILE_ATTRIBUTE_NORMAL,
1441 INTERNAL_OPEN_ONLY,
1442 NULL);
1444 if (!fsp) {
1445 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1446 driverpath, errno));
1447 *perr = WERR_ACCESS_DENIED;
1448 goto error_exit;
1449 } else {
1450 uint32 major;
1451 uint32 minor;
1452 int ret = get_file_version(fsp, driverpath, &major, &minor);
1453 if (ret == -1) goto error_exit;
1455 if (!ret) {
1456 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1457 goto error_exit;
1461 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1462 * for more details. Version in this case is not just the version of the
1463 * file, but the version in the sense of kernal mode (2) vs. user mode
1464 * (3) drivers. Other bits of the version fields are the version info.
1465 * JRR 010716
1467 cversion = major & 0x0000ffff;
1468 switch (cversion) {
1469 case 2: /* WinNT drivers */
1470 case 3: /* Win2K drivers */
1471 break;
1473 default:
1474 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1475 driverpath, cversion));
1476 goto error_exit;
1479 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1480 driverpath, major, minor));
1483 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1484 driverpath, cversion));
1486 close_file(fsp, NORMAL_CLOSE);
1487 close_cnum(conn, user->vuid);
1488 unbecome_user();
1489 *perr = WERR_OK;
1490 return cversion;
1493 error_exit:
1495 if(fsp)
1496 close_file(fsp, NORMAL_CLOSE);
1498 close_cnum(conn, user->vuid);
1499 unbecome_user();
1500 return -1;
1503 /****************************************************************************
1504 ****************************************************************************/
1505 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1506 struct current_user *user)
1508 const char *architecture;
1509 fstring new_name;
1510 char *p;
1511 int i;
1512 WERROR err;
1514 /* clean up the driver name.
1515 * we can get .\driver.dll
1516 * or worse c:\windows\system\driver.dll !
1518 /* using an intermediate string to not have overlaping memcpy()'s */
1519 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1520 fstrcpy(new_name, p+1);
1521 fstrcpy(driver->driverpath, new_name);
1524 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1525 fstrcpy(new_name, p+1);
1526 fstrcpy(driver->datafile, new_name);
1529 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1530 fstrcpy(new_name, p+1);
1531 fstrcpy(driver->configfile, new_name);
1534 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1535 fstrcpy(new_name, p+1);
1536 fstrcpy(driver->helpfile, new_name);
1539 if (driver->dependentfiles) {
1540 for (i=0; *driver->dependentfiles[i]; i++) {
1541 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1542 fstrcpy(new_name, p+1);
1543 fstrcpy(driver->dependentfiles[i], new_name);
1548 architecture = get_short_archi(driver->environment);
1550 /* jfm:7/16/2000 the client always sends the cversion=0.
1551 * The server should check which version the driver is by reading
1552 * the PE header of driver->driverpath.
1554 * For Windows 95/98 the version is 0 (so the value sent is correct)
1555 * For Windows NT (the architecture doesn't matter)
1556 * NT 3.1: cversion=0
1557 * NT 3.5/3.51: cversion=1
1558 * NT 4: cversion=2
1559 * NT2K: cversion=3
1561 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1562 return err;
1564 return WERR_OK;
1567 /****************************************************************************
1568 ****************************************************************************/
1569 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1571 const char *architecture;
1572 fstring new_name;
1573 char *p;
1574 int i;
1575 WERROR err;
1577 /* clean up the driver name.
1578 * we can get .\driver.dll
1579 * or worse c:\windows\system\driver.dll !
1581 /* using an intermediate string to not have overlaping memcpy()'s */
1582 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1583 fstrcpy(new_name, p+1);
1584 fstrcpy(driver->driverpath, new_name);
1587 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1588 fstrcpy(new_name, p+1);
1589 fstrcpy(driver->datafile, new_name);
1592 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1593 fstrcpy(new_name, p+1);
1594 fstrcpy(driver->configfile, new_name);
1597 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1598 fstrcpy(new_name, p+1);
1599 fstrcpy(driver->helpfile, new_name);
1602 if (driver->dependentfiles) {
1603 for (i=0; *driver->dependentfiles[i]; i++) {
1604 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1605 fstrcpy(new_name, p+1);
1606 fstrcpy(driver->dependentfiles[i], new_name);
1611 architecture = get_short_archi(driver->environment);
1613 /* jfm:7/16/2000 the client always sends the cversion=0.
1614 * The server should check which version the driver is by reading
1615 * the PE header of driver->driverpath.
1617 * For Windows 95/98 the version is 0 (so the value sent is correct)
1618 * For Windows NT (the architecture doesn't matter)
1619 * NT 3.1: cversion=0
1620 * NT 3.5/3.51: cversion=1
1621 * NT 4: cversion=2
1622 * NT2K: cversion=3
1625 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1626 return err;
1628 return WERR_OK;
1631 /****************************************************************************
1632 ****************************************************************************/
1633 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1634 uint32 level, struct current_user *user)
1636 switch (level) {
1637 case 3:
1639 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1640 driver=driver_abstract.info_3;
1641 return clean_up_driver_struct_level_3(driver, user);
1643 case 6:
1645 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1646 driver=driver_abstract.info_6;
1647 return clean_up_driver_struct_level_6(driver, user);
1649 default:
1650 return WERR_INVALID_PARAM;
1654 /****************************************************************************
1655 This function sucks and should be replaced. JRA.
1656 ****************************************************************************/
1658 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1660 dst->cversion = src->version;
1662 fstrcpy( dst->name, src->name);
1663 fstrcpy( dst->environment, src->environment);
1664 fstrcpy( dst->driverpath, src->driverpath);
1665 fstrcpy( dst->datafile, src->datafile);
1666 fstrcpy( dst->configfile, src->configfile);
1667 fstrcpy( dst->helpfile, src->helpfile);
1668 fstrcpy( dst->monitorname, src->monitorname);
1669 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1670 dst->dependentfiles = src->dependentfiles;
1673 #if 0 /* Debugging function */
1675 static char* ffmt(unsigned char *c){
1676 int i;
1677 static char ffmt_str[17];
1679 for (i=0; i<16; i++) {
1680 if ((c[i] < ' ') || (c[i] > '~'))
1681 ffmt_str[i]='.';
1682 else
1683 ffmt_str[i]=c[i];
1685 ffmt_str[16]='\0';
1686 return ffmt_str;
1689 #endif
1691 /****************************************************************************
1692 ****************************************************************************/
1693 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1694 struct current_user *user, WERROR *perr)
1696 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1697 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1698 const char *architecture;
1699 pstring new_dir;
1700 pstring old_name;
1701 pstring new_name;
1702 DATA_BLOB null_pw;
1703 connection_struct *conn;
1704 NTSTATUS nt_status;
1705 pstring inbuf;
1706 pstring outbuf;
1707 fstring res_type;
1708 BOOL bad_path;
1709 SMB_STRUCT_STAT st;
1710 int ver = 0;
1711 int i;
1712 int err;
1714 memset(inbuf, '\0', sizeof(inbuf));
1715 memset(outbuf, '\0', sizeof(outbuf));
1716 *perr = WERR_OK;
1718 if (level==3)
1719 driver=driver_abstract.info_3;
1720 else if (level==6) {
1721 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1722 driver = &converted_driver;
1723 } else {
1724 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1725 return WERR_UNKNOWN_LEVEL;
1728 architecture = get_short_archi(driver->environment);
1731 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1732 * Note we must be root to do this.
1735 null_pw = data_blob(NULL, 0);
1736 fstrcpy(res_type, "A:");
1737 become_root();
1738 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1739 unbecome_root();
1741 if (conn == NULL) {
1742 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1743 *perr = ntstatus_to_werror(nt_status);
1744 return WERR_NO_SUCH_SHARE;
1748 * Save who we are - we are temporarily becoming the connection user.
1751 if (!become_user(conn, conn->vuid)) {
1752 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1753 return WERR_ACCESS_DENIED;
1757 * make the directories version and version\driver_name
1758 * under the architecture directory.
1760 DEBUG(5,("Creating first directory\n"));
1761 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1762 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1763 mkdir_internal(conn, new_dir, bad_path);
1765 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1766 * listed for this driver which has already been moved, skip it (note:
1767 * drivers may list the same file name several times. Then check if the
1768 * file already exists in archi\cversion\, if so, check that the version
1769 * info (or time stamps if version info is unavailable) is newer (or the
1770 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1771 * Otherwise, delete the file.
1773 * If a file is not moved to archi\cversion\ because of an error, all the
1774 * rest of the 'unmoved' driver files are removed from archi\. If one or
1775 * more of the driver's files was already moved to archi\cversion\, it
1776 * potentially leaves the driver in a partially updated state. Version
1777 * trauma will most likely occur if an client attempts to use any printer
1778 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1779 * done is appropriate... later JRR
1782 DEBUG(5,("Moving files now !\n"));
1784 if (driver->driverpath && strlen(driver->driverpath)) {
1785 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1786 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1787 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1788 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1789 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1790 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1791 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1792 new_name, old_name));
1793 *perr = WERR_ACCESS_DENIED;
1794 ver = -1;
1799 if (driver->datafile && strlen(driver->datafile)) {
1800 if (!strequal(driver->datafile, driver->driverpath)) {
1801 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1802 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1803 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1804 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1805 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1806 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1807 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1808 new_name, old_name));
1809 *perr = WERR_ACCESS_DENIED;
1810 ver = -1;
1816 if (driver->configfile && strlen(driver->configfile)) {
1817 if (!strequal(driver->configfile, driver->driverpath) &&
1818 !strequal(driver->configfile, driver->datafile)) {
1819 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1820 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1821 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1822 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1823 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1824 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1825 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1826 new_name, old_name));
1827 *perr = WERR_ACCESS_DENIED;
1828 ver = -1;
1834 if (driver->helpfile && strlen(driver->helpfile)) {
1835 if (!strequal(driver->helpfile, driver->driverpath) &&
1836 !strequal(driver->helpfile, driver->datafile) &&
1837 !strequal(driver->helpfile, driver->configfile)) {
1838 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1839 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1840 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1841 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1842 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1843 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1844 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1845 new_name, old_name));
1846 *perr = WERR_ACCESS_DENIED;
1847 ver = -1;
1853 if (driver->dependentfiles) {
1854 for (i=0; *driver->dependentfiles[i]; i++) {
1855 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1856 !strequal(driver->dependentfiles[i], driver->datafile) &&
1857 !strequal(driver->dependentfiles[i], driver->configfile) &&
1858 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1859 int j;
1860 for (j=0; j < i; j++) {
1861 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1862 goto NextDriver;
1866 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1867 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1868 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1869 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1870 if ( !copy_file(new_name, old_name, conn,
1871 OPENX_FILE_EXISTS_TRUNCATE|
1872 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1873 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1874 new_name, old_name));
1875 *perr = WERR_ACCESS_DENIED;
1876 ver = -1;
1880 NextDriver: ;
1884 close_cnum(conn, user->vuid);
1885 unbecome_user();
1887 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1890 /****************************************************************************
1891 ****************************************************************************/
1892 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1894 int len, buflen;
1895 const char *architecture;
1896 pstring directory;
1897 fstring temp_name;
1898 pstring key;
1899 char *buf;
1900 int i, ret;
1901 TDB_DATA kbuf, dbuf;
1903 architecture = get_short_archi(driver->environment);
1905 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1906 * \\server is added in the rpc server layer.
1907 * It does make sense to NOT store the server's name in the printer TDB.
1910 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1912 /* .inf files do not always list a file for each of the four standard files.
1913 * Don't prepend a path to a null filename, or client claims:
1914 * "The server on which the printer resides does not have a suitable
1915 * <printer driver name> printer driver installed. Click OK if you
1916 * wish to install the driver on your local machine."
1918 if (strlen(driver->driverpath)) {
1919 fstrcpy(temp_name, driver->driverpath);
1920 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1923 if (strlen(driver->datafile)) {
1924 fstrcpy(temp_name, driver->datafile);
1925 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1928 if (strlen(driver->configfile)) {
1929 fstrcpy(temp_name, driver->configfile);
1930 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1933 if (strlen(driver->helpfile)) {
1934 fstrcpy(temp_name, driver->helpfile);
1935 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1938 if (driver->dependentfiles) {
1939 for (i=0; *driver->dependentfiles[i]; i++) {
1940 fstrcpy(temp_name, driver->dependentfiles[i]);
1941 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1945 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1947 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1949 buf = NULL;
1950 len = buflen = 0;
1952 again:
1953 len = 0;
1954 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1955 driver->cversion,
1956 driver->name,
1957 driver->environment,
1958 driver->driverpath,
1959 driver->datafile,
1960 driver->configfile,
1961 driver->helpfile,
1962 driver->monitorname,
1963 driver->defaultdatatype);
1965 if (driver->dependentfiles) {
1966 for (i=0; *driver->dependentfiles[i]; i++) {
1967 len += tdb_pack(buf+len, buflen-len, "f",
1968 driver->dependentfiles[i]);
1972 if (len != buflen) {
1973 buf = (char *)SMB_REALLOC(buf, len);
1974 if (!buf) {
1975 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1976 ret = -1;
1977 goto done;
1979 buflen = len;
1980 goto again;
1984 kbuf.dptr = key;
1985 kbuf.dsize = strlen(key)+1;
1986 dbuf.dptr = buf;
1987 dbuf.dsize = len;
1989 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1991 done:
1992 if (ret)
1993 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1995 SAFE_FREE(buf);
1996 return ret;
1999 /****************************************************************************
2000 ****************************************************************************/
2001 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2003 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2005 ZERO_STRUCT(info3);
2006 info3.cversion = driver->version;
2007 fstrcpy(info3.name,driver->name);
2008 fstrcpy(info3.environment,driver->environment);
2009 fstrcpy(info3.driverpath,driver->driverpath);
2010 fstrcpy(info3.datafile,driver->datafile);
2011 fstrcpy(info3.configfile,driver->configfile);
2012 fstrcpy(info3.helpfile,driver->helpfile);
2013 fstrcpy(info3.monitorname,driver->monitorname);
2014 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2015 info3.dependentfiles = driver->dependentfiles;
2017 return add_a_printer_driver_3(&info3);
2021 /****************************************************************************
2022 ****************************************************************************/
2023 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2025 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2027 ZERO_STRUCT(info);
2029 fstrcpy(info.name, driver);
2030 fstrcpy(info.defaultdatatype, "RAW");
2032 fstrcpy(info.driverpath, "");
2033 fstrcpy(info.datafile, "");
2034 fstrcpy(info.configfile, "");
2035 fstrcpy(info.helpfile, "");
2037 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2038 return WERR_NOMEM;
2040 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2041 fstrcpy(info.dependentfiles[0], "");
2043 *info_ptr = memdup(&info, sizeof(info));
2045 return WERR_OK;
2048 /****************************************************************************
2049 ****************************************************************************/
2050 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2052 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2053 TDB_DATA kbuf, dbuf;
2054 const char *architecture;
2055 int len = 0;
2056 int i;
2057 pstring key;
2059 ZERO_STRUCT(driver);
2061 architecture = get_short_archi(arch);
2063 if ( !architecture )
2064 return WERR_UNKNOWN_PRINTER_DRIVER;
2066 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2068 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2069 version = 0;
2071 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2073 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2075 kbuf.dptr = key;
2076 kbuf.dsize = strlen(key)+1;
2078 dbuf = tdb_fetch(tdb_drivers, kbuf);
2079 if (!dbuf.dptr)
2080 return WERR_UNKNOWN_PRINTER_DRIVER;
2082 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2083 &driver.cversion,
2084 driver.name,
2085 driver.environment,
2086 driver.driverpath,
2087 driver.datafile,
2088 driver.configfile,
2089 driver.helpfile,
2090 driver.monitorname,
2091 driver.defaultdatatype);
2093 i=0;
2094 while (len < dbuf.dsize) {
2095 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2096 if ( !driver.dependentfiles ) {
2097 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2098 break;
2101 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2102 &driver.dependentfiles[i]);
2103 i++;
2106 if ( driver.dependentfiles )
2107 fstrcpy( driver.dependentfiles[i], "" );
2109 SAFE_FREE(dbuf.dptr);
2111 if (len != dbuf.dsize) {
2112 SAFE_FREE(driver.dependentfiles);
2114 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2117 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2119 return WERR_OK;
2122 /****************************************************************************
2123 Debugging function, dump at level 6 the struct in the logs.
2124 ****************************************************************************/
2126 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2128 uint32 result;
2129 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2130 int i;
2132 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2134 switch (level)
2136 case 3:
2138 if (driver.info_3 == NULL)
2139 result=5;
2140 else {
2141 info3=driver.info_3;
2143 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2144 DEBUGADD(20,("name:[%s]\n", info3->name));
2145 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2146 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2147 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2148 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2149 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2150 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2151 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2153 for (i=0; info3->dependentfiles &&
2154 *info3->dependentfiles[i]; i++) {
2155 DEBUGADD(20,("dependentfile:[%s]\n",
2156 info3->dependentfiles[i]));
2158 result=0;
2160 break;
2162 default:
2163 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2164 result=1;
2165 break;
2168 return result;
2171 /****************************************************************************
2172 ****************************************************************************/
2173 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2175 int len = 0;
2177 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2179 if (!nt_devmode)
2180 return len;
2182 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2183 nt_devmode->devicename,
2184 nt_devmode->formname,
2186 nt_devmode->specversion,
2187 nt_devmode->driverversion,
2188 nt_devmode->size,
2189 nt_devmode->driverextra,
2190 nt_devmode->orientation,
2191 nt_devmode->papersize,
2192 nt_devmode->paperlength,
2193 nt_devmode->paperwidth,
2194 nt_devmode->scale,
2195 nt_devmode->copies,
2196 nt_devmode->defaultsource,
2197 nt_devmode->printquality,
2198 nt_devmode->color,
2199 nt_devmode->duplex,
2200 nt_devmode->yresolution,
2201 nt_devmode->ttoption,
2202 nt_devmode->collate,
2203 nt_devmode->logpixels,
2205 nt_devmode->fields,
2206 nt_devmode->bitsperpel,
2207 nt_devmode->pelswidth,
2208 nt_devmode->pelsheight,
2209 nt_devmode->displayflags,
2210 nt_devmode->displayfrequency,
2211 nt_devmode->icmmethod,
2212 nt_devmode->icmintent,
2213 nt_devmode->mediatype,
2214 nt_devmode->dithertype,
2215 nt_devmode->reserved1,
2216 nt_devmode->reserved2,
2217 nt_devmode->panningwidth,
2218 nt_devmode->panningheight,
2219 nt_devmode->nt_dev_private);
2222 if (nt_devmode->nt_dev_private) {
2223 len += tdb_pack(buf+len, buflen-len, "B",
2224 nt_devmode->driverextra,
2225 nt_devmode->nt_dev_private);
2228 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2230 return len;
2233 /****************************************************************************
2234 Pack all values in all printer keys
2235 ***************************************************************************/
2237 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2239 int len = 0;
2240 int i, j;
2241 REGISTRY_VALUE *val;
2242 REGVAL_CTR *val_ctr;
2243 pstring path;
2244 int num_values;
2246 if ( !data )
2247 return 0;
2249 /* loop over all keys */
2251 for ( i=0; i<data->num_keys; i++ ) {
2252 val_ctr = data->keys[i].values;
2253 num_values = regval_ctr_numvals( val_ctr );
2255 /* pack the keyname followed by a empty value */
2257 len += tdb_pack(buf+len, buflen-len, "pPdB",
2258 &data->keys[i].name,
2259 data->keys[i].name,
2260 REG_NONE,
2262 NULL);
2264 /* now loop over all values */
2266 for ( j=0; j<num_values; j++ ) {
2267 /* pathname should be stored as <key>\<value> */
2269 val = regval_ctr_specific_value( val_ctr, j );
2270 pstrcpy( path, data->keys[i].name );
2271 pstrcat( path, "\\" );
2272 pstrcat( path, regval_name(val) );
2274 len += tdb_pack(buf+len, buflen-len, "pPdB",
2275 val,
2276 path,
2277 regval_type(val),
2278 regval_size(val),
2279 regval_data_p(val) );
2281 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2286 /* terminator */
2288 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2290 return len;
2294 /****************************************************************************
2295 Delete a printer - this just deletes the printer info file, any open
2296 handles are not affected.
2297 ****************************************************************************/
2299 uint32 del_a_printer(const char *sharename)
2301 pstring key;
2302 TDB_DATA kbuf;
2303 pstring printdb_path;
2305 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2306 kbuf.dptr=key;
2307 kbuf.dsize=strlen(key)+1;
2308 tdb_delete(tdb_printers, kbuf);
2310 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2311 kbuf.dptr=key;
2312 kbuf.dsize=strlen(key)+1;
2313 tdb_delete(tdb_printers, kbuf);
2315 close_all_print_db();
2317 if (geteuid() == 0) {
2318 pstrcpy(printdb_path, lock_path("printing/"));
2319 pstrcat(printdb_path, sharename);
2320 pstrcat(printdb_path, ".tdb");
2322 unlink(printdb_path);
2325 return 0;
2328 /****************************************************************************
2329 ****************************************************************************/
2330 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2332 char *buf;
2333 int buflen, len;
2334 WERROR ret;
2335 TDB_DATA kbuf, dbuf;
2338 * in addprinter: no servername and the printer is the name
2339 * in setprinter: servername is \\server
2340 * and printer is \\server\\printer
2342 * Samba manages only local printers.
2343 * we currently don't support things like i
2344 * path=\\other_server\printer
2346 * We only store the printername, not \\server\printername
2349 if ( info->servername[0] != '\0' ) {
2350 trim_string(info->printername, info->servername, NULL);
2351 trim_char(info->printername, '\\', '\0');
2352 info->servername[0]='\0';
2356 * JFM: one day I'll forget.
2357 * below that's info->portname because that's the SAMBA sharename
2358 * and I made NT 'thinks' it's the portname
2359 * the info->sharename is the thing you can name when you add a printer
2360 * that's the short-name when you create shared printer for 95/98
2361 * So I've made a limitation in SAMBA: you can only have 1 printer model
2362 * behind a SAMBA share.
2365 buf = NULL;
2366 buflen = 0;
2368 again:
2369 len = 0;
2370 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2371 info->attributes,
2372 info->priority,
2373 info->default_priority,
2374 info->starttime,
2375 info->untiltime,
2376 info->status,
2377 info->cjobs,
2378 info->averageppm,
2379 info->changeid,
2380 info->c_setprinter,
2381 info->setuptime,
2382 info->servername,
2383 info->printername,
2384 info->sharename,
2385 info->portname,
2386 info->drivername,
2387 info->comment,
2388 info->location,
2389 info->sepfile,
2390 info->printprocessor,
2391 info->datatype,
2392 info->parameters);
2394 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2396 len += pack_values( info->data, buf+len, buflen-len );
2398 if (buflen != len) {
2399 buf = (char *)SMB_REALLOC(buf, len);
2400 if (!buf) {
2401 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2402 ret = WERR_NOMEM;
2403 goto done;
2405 buflen = len;
2406 goto again;
2410 kbuf = make_printer_tdbkey( info->sharename );
2412 dbuf.dptr = buf;
2413 dbuf.dsize = len;
2415 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2417 done:
2418 if (!W_ERROR_IS_OK(ret))
2419 DEBUG(8, ("error updating printer to tdb on disk\n"));
2421 SAFE_FREE(buf);
2423 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2424 info->sharename, info->drivername, info->portname, len));
2426 return ret;
2430 /****************************************************************************
2431 Malloc and return an NT devicemode.
2432 ****************************************************************************/
2434 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2437 char adevice[MAXDEVICENAME];
2438 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2440 if (nt_devmode == NULL) {
2441 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2442 return NULL;
2445 ZERO_STRUCTP(nt_devmode);
2447 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2448 fstrcpy(nt_devmode->devicename, adevice);
2450 fstrcpy(nt_devmode->formname, "Letter");
2452 nt_devmode->specversion = 0x0401;
2453 nt_devmode->driverversion = 0x0400;
2454 nt_devmode->size = 0x00DC;
2455 nt_devmode->driverextra = 0x0000;
2456 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2457 DEFAULTSOURCE | COPIES | SCALE |
2458 PAPERSIZE | ORIENTATION;
2459 nt_devmode->orientation = 1;
2460 nt_devmode->papersize = PAPER_LETTER;
2461 nt_devmode->paperlength = 0;
2462 nt_devmode->paperwidth = 0;
2463 nt_devmode->scale = 0x64;
2464 nt_devmode->copies = 1;
2465 nt_devmode->defaultsource = BIN_FORMSOURCE;
2466 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2467 nt_devmode->color = COLOR_MONOCHROME;
2468 nt_devmode->duplex = DUP_SIMPLEX;
2469 nt_devmode->yresolution = 0;
2470 nt_devmode->ttoption = TT_SUBDEV;
2471 nt_devmode->collate = COLLATE_FALSE;
2472 nt_devmode->icmmethod = 0;
2473 nt_devmode->icmintent = 0;
2474 nt_devmode->mediatype = 0;
2475 nt_devmode->dithertype = 0;
2477 /* non utilisés par un driver d'imprimante */
2478 nt_devmode->logpixels = 0;
2479 nt_devmode->bitsperpel = 0;
2480 nt_devmode->pelswidth = 0;
2481 nt_devmode->pelsheight = 0;
2482 nt_devmode->displayflags = 0;
2483 nt_devmode->displayfrequency = 0;
2484 nt_devmode->reserved1 = 0;
2485 nt_devmode->reserved2 = 0;
2486 nt_devmode->panningwidth = 0;
2487 nt_devmode->panningheight = 0;
2489 nt_devmode->nt_dev_private = NULL;
2490 return nt_devmode;
2493 /****************************************************************************
2494 Deepcopy an NT devicemode.
2495 ****************************************************************************/
2497 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2499 NT_DEVICEMODE *new_nt_devicemode = NULL;
2501 if ( !nt_devicemode )
2502 return NULL;
2504 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2505 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2506 return NULL;
2509 new_nt_devicemode->nt_dev_private = NULL;
2510 if (nt_devicemode->nt_dev_private != NULL) {
2511 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2512 SAFE_FREE(new_nt_devicemode);
2513 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2514 return NULL;
2518 return new_nt_devicemode;
2521 /****************************************************************************
2522 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2523 ****************************************************************************/
2525 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2527 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2529 if(nt_devmode == NULL)
2530 return;
2532 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2534 SAFE_FREE(nt_devmode->nt_dev_private);
2535 SAFE_FREE(*devmode_ptr);
2538 /****************************************************************************
2539 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2540 ****************************************************************************/
2542 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2544 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2546 if ( !info )
2547 return;
2549 free_nt_devicemode(&info->devmode);
2551 TALLOC_FREE( *info_ptr );
2555 /****************************************************************************
2556 ****************************************************************************/
2557 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2559 int len = 0;
2560 int extra_len = 0;
2561 NT_DEVICEMODE devmode;
2563 ZERO_STRUCT(devmode);
2565 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2567 if (!*nt_devmode) return len;
2569 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2570 devmode.devicename,
2571 devmode.formname,
2573 &devmode.specversion,
2574 &devmode.driverversion,
2575 &devmode.size,
2576 &devmode.driverextra,
2577 &devmode.orientation,
2578 &devmode.papersize,
2579 &devmode.paperlength,
2580 &devmode.paperwidth,
2581 &devmode.scale,
2582 &devmode.copies,
2583 &devmode.defaultsource,
2584 &devmode.printquality,
2585 &devmode.color,
2586 &devmode.duplex,
2587 &devmode.yresolution,
2588 &devmode.ttoption,
2589 &devmode.collate,
2590 &devmode.logpixels,
2592 &devmode.fields,
2593 &devmode.bitsperpel,
2594 &devmode.pelswidth,
2595 &devmode.pelsheight,
2596 &devmode.displayflags,
2597 &devmode.displayfrequency,
2598 &devmode.icmmethod,
2599 &devmode.icmintent,
2600 &devmode.mediatype,
2601 &devmode.dithertype,
2602 &devmode.reserved1,
2603 &devmode.reserved2,
2604 &devmode.panningwidth,
2605 &devmode.panningheight,
2606 &devmode.nt_dev_private);
2608 if (devmode.nt_dev_private) {
2609 /* the len in tdb_unpack is an int value and
2610 * devmode.driverextra is only a short
2612 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2613 devmode.driverextra=(uint16)extra_len;
2615 /* check to catch an invalid TDB entry so we don't segfault */
2616 if (devmode.driverextra == 0) {
2617 devmode.nt_dev_private = NULL;
2621 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2623 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2624 if (devmode.nt_dev_private)
2625 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2627 return len;
2630 /****************************************************************************
2631 Allocate and initialize a new slot.
2632 ***************************************************************************/
2634 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2636 NT_PRINTER_KEY *d;
2637 int key_index;
2639 if ( !name || !data )
2640 return -1;
2642 /* allocate another slot in the NT_PRINTER_KEY array */
2644 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2645 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2646 return -1;
2649 data->keys = d;
2651 key_index = data->num_keys;
2653 /* initialze new key */
2655 data->keys[key_index].name = talloc_strdup( data, name );
2657 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2658 return -1;
2660 data->num_keys++;
2662 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2664 return key_index;
2667 /****************************************************************************
2668 search for a registry key name in the existing printer data
2669 ***************************************************************************/
2671 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2673 int i;
2675 for ( i=0; i<data->num_keys; i++ ) {
2676 if ( strequal( data->keys[i].name, name ) ) {
2678 /* cleanup memory */
2680 TALLOC_FREE( data->keys[i].name );
2681 TALLOC_FREE( data->keys[i].values );
2683 /* if not the end of the array, move remaining elements down one slot */
2685 data->num_keys--;
2686 if ( data->num_keys && (i < data->num_keys) )
2687 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2689 break;
2694 return data->num_keys;
2697 /****************************************************************************
2698 search for a registry key name in the existing printer data
2699 ***************************************************************************/
2701 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2703 int key_index = -1;
2704 int i;
2706 if ( !data || !name )
2707 return -1;
2709 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2711 /* loop over all existing keys */
2713 for ( i=0; i<data->num_keys; i++ ) {
2714 if ( strequal(data->keys[i].name, name) ) {
2715 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2716 key_index = i;
2717 break;
2722 return key_index;
2725 /****************************************************************************
2726 ***************************************************************************/
2728 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2730 int i, j;
2731 int key_len;
2732 int num_subkeys = 0;
2733 char *p;
2734 fstring *subkeys_ptr = NULL;
2735 fstring subkeyname;
2737 if ( !data )
2738 return 0;
2740 if ( !key )
2741 return -1;
2743 /* special case of asking for the top level printer data registry key names */
2745 if ( strlen(key) == 0 ) {
2746 for ( i=0; i<data->num_keys; i++ ) {
2748 /* found a match, so allocate space and copy the name */
2750 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2751 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2752 num_subkeys+1));
2753 return -1;
2756 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2757 num_subkeys++;
2760 goto done;
2763 /* asking for the subkeys of some key */
2764 /* subkey paths are stored in the key name using '\' as the delimiter */
2766 for ( i=0; i<data->num_keys; i++ ) {
2767 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2769 /* if we found the exact key, then break */
2770 key_len = strlen( key );
2771 if ( strlen(data->keys[i].name) == key_len )
2772 break;
2774 /* get subkey path */
2776 p = data->keys[i].name + key_len;
2777 if ( *p == '\\' )
2778 p++;
2779 fstrcpy( subkeyname, p );
2780 if ( (p = strchr( subkeyname, '\\' )) )
2781 *p = '\0';
2783 /* don't add a key more than once */
2785 for ( j=0; j<num_subkeys; j++ ) {
2786 if ( strequal( subkeys_ptr[j], subkeyname ) )
2787 break;
2790 if ( j != num_subkeys )
2791 continue;
2793 /* found a match, so allocate space and copy the name */
2795 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2796 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2797 num_subkeys+1));
2798 return 0;
2801 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2802 num_subkeys++;
2807 /* return error if the key was not found */
2809 if ( i == data->num_keys ) {
2810 SAFE_FREE(subkeys_ptr);
2811 return -1;
2814 done:
2815 /* tag off the end */
2817 if (num_subkeys)
2818 fstrcpy(subkeys_ptr[num_subkeys], "" );
2820 *subkeys = subkeys_ptr;
2822 return num_subkeys;
2825 #ifdef HAVE_ADS
2826 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2827 const char *sz)
2829 smb_ucs2_t conv_str[1024];
2830 size_t str_size;
2832 regval_ctr_delvalue(ctr, val_name);
2833 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2834 STR_TERMINATE | STR_NOALIGN);
2835 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2836 (char *) conv_str, str_size);
2839 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2840 uint32 dword)
2842 regval_ctr_delvalue(ctr, val_name);
2843 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2844 (char *) &dword, sizeof(dword));
2847 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2848 BOOL b)
2850 uint8 bin_bool = (b ? 1 : 0);
2851 regval_ctr_delvalue(ctr, val_name);
2852 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2853 (char *) &bin_bool, sizeof(bin_bool));
2856 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2857 const char *multi_sz)
2859 smb_ucs2_t *conv_strs = NULL;
2860 size_t str_size;
2862 /* a multi-sz has to have a null string terminator, i.e., the last
2863 string must be followed by two nulls */
2864 str_size = strlen(multi_sz) + 2;
2865 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2866 if (!conv_strs) {
2867 return;
2870 /* Change to byte units. */
2871 str_size *= sizeof(smb_ucs2_t);
2872 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2873 STR_TERMINATE | STR_NOALIGN);
2875 regval_ctr_delvalue(ctr, val_name);
2876 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2877 (char *) conv_strs, str_size);
2878 safe_free(conv_strs);
2882 /****************************************************************************
2883 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2885 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2886 * @return BOOL indicating success or failure
2887 ***************************************************************************/
2889 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2891 REGVAL_CTR *ctr = NULL;
2892 fstring longname;
2893 fstring dnssuffix;
2894 char *allocated_string = NULL;
2895 const char *ascii_str;
2896 int i;
2898 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2899 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2900 ctr = info2->data->keys[i].values;
2902 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2903 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2905 /* we make the assumption that the netbios name is the same
2906 as the DNS name sinc ethe former will be what we used to
2907 join the domain */
2909 if ( get_mydnsdomname( dnssuffix ) )
2910 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2911 else
2912 fstrcpy( longname, global_myname() );
2914 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2916 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2917 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2918 SAFE_FREE(allocated_string);
2920 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2921 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2922 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2923 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2924 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2925 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2926 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2927 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2928 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2930 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2931 (info2->attributes &
2932 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2934 switch (info2->attributes & 0x3) {
2935 case 0:
2936 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2937 break;
2938 case 1:
2939 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2940 break;
2941 case 2:
2942 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2943 break;
2944 default:
2945 ascii_str = "unknown";
2947 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2949 return True;
2952 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2953 struct uuid guid)
2955 int i;
2956 REGVAL_CTR *ctr=NULL;
2958 /* find the DsSpooler key */
2959 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2960 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2961 ctr = info2->data->keys[i].values;
2963 regval_ctr_delvalue(ctr, "objectGUID");
2964 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2965 (char *) &guid, sizeof(struct uuid));
2968 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2969 NT_PRINTER_INFO_LEVEL *printer)
2971 ADS_STATUS ads_rc;
2972 void *res;
2973 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2974 char *srv_dn_utf8, **srv_cn_utf8;
2975 TALLOC_CTX *ctx;
2976 ADS_MODLIST mods;
2977 const char *attrs[] = {"objectGUID", NULL};
2978 struct uuid guid;
2979 WERROR win_rc = WERR_OK;
2981 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2983 /* figure out where to publish */
2984 ads_find_machine_acct(ads, &res, global_myname());
2986 /* We use ldap_get_dn here as we need the answer
2987 * in utf8 to call ldap_explode_dn(). JRA. */
2989 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2990 if (!srv_dn_utf8) {
2991 ads_destroy(&ads);
2992 return WERR_SERVER_UNAVAILABLE;
2994 ads_msgfree(ads, res);
2995 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2996 if (!srv_cn_utf8) {
2997 ldap_memfree(srv_dn_utf8);
2998 ads_destroy(&ads);
2999 return WERR_SERVER_UNAVAILABLE;
3001 /* Now convert to CH_UNIX. */
3002 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3003 ldap_memfree(srv_dn_utf8);
3004 ldap_memfree(srv_cn_utf8);
3005 ads_destroy(&ads);
3006 return WERR_SERVER_UNAVAILABLE;
3008 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3009 ldap_memfree(srv_dn_utf8);
3010 ldap_memfree(srv_cn_utf8);
3011 ads_destroy(&ads);
3012 SAFE_FREE(srv_dn);
3013 return WERR_SERVER_UNAVAILABLE;
3016 ldap_memfree(srv_dn_utf8);
3017 ldap_memfree(srv_cn_utf8);
3019 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
3020 printer->info_2->sharename, srv_dn);
3022 SAFE_FREE(srv_dn);
3023 SAFE_FREE(srv_cn_0);
3025 /* build the ads mods */
3026 ctx = talloc_init("nt_printer_publish_ads");
3027 mods = ads_init_mods(ctx);
3029 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3030 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3031 printer->info_2->sharename);
3033 /* publish it */
3034 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3035 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3036 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3038 if (!ADS_ERR_OK(ads_rc))
3039 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3041 talloc_destroy(ctx);
3043 /* retreive the guid and store it locally */
3044 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3045 ZERO_STRUCT(guid);
3046 ads_pull_guid(ads, res, &guid);
3047 ads_msgfree(ads, res);
3048 store_printer_guid(printer->info_2, guid);
3049 win_rc = mod_a_printer(printer, 2);
3052 SAFE_FREE(prt_dn);
3053 return win_rc;
3056 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3057 NT_PRINTER_INFO_LEVEL *printer)
3059 ADS_STATUS ads_rc;
3060 void *res;
3061 char *prt_dn = NULL;
3063 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3065 /* remove the printer from the directory */
3066 ads_rc = ads_find_printer_on_server(ads, &res,
3067 printer->info_2->sharename, global_myname());
3069 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3070 prt_dn = ads_get_dn(ads, res);
3071 ads_rc = ads_del_dn(ads, prt_dn);
3072 ads_memfree(ads, prt_dn);
3075 ads_msgfree(ads, res);
3076 return WERR_OK;
3079 /****************************************************************************
3080 * Publish a printer in the directory
3082 * @param snum describing printer service
3083 * @return WERROR indicating status of publishing
3084 ***************************************************************************/
3086 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3088 ADS_STATUS ads_rc;
3089 ADS_STRUCT *ads = NULL;
3090 NT_PRINTER_INFO_LEVEL *printer = NULL;
3091 WERROR win_rc;
3093 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3094 if (!W_ERROR_IS_OK(win_rc))
3095 goto done;
3097 switch (action) {
3098 case SPOOL_DS_PUBLISH:
3099 case SPOOL_DS_UPDATE:
3100 /* set the DsSpooler info and attributes */
3101 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3102 win_rc = WERR_NOMEM;
3103 goto done;
3106 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3107 break;
3108 case SPOOL_DS_UNPUBLISH:
3109 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3110 break;
3111 default:
3112 win_rc = WERR_NOT_SUPPORTED;
3113 goto done;
3116 win_rc = mod_a_printer(printer, 2);
3117 if (!W_ERROR_IS_OK(win_rc)) {
3118 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3119 goto done;
3122 ads = ads_init(NULL, NULL, NULL);
3123 if (!ads) {
3124 DEBUG(3, ("ads_init() failed\n"));
3125 win_rc = WERR_SERVER_UNAVAILABLE;
3126 goto done;
3128 #ifdef HAVE_KCM
3129 setenv(KRB5_ENV_CCNAME, "KCM:SYSTEM", 1);
3130 #else
3131 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3132 #endif
3133 SAFE_FREE(ads->auth.password);
3134 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3135 NULL, NULL);
3137 /* ads_connect() will find the DC for us */
3138 ads_rc = ads_connect(ads);
3139 if (!ADS_ERR_OK(ads_rc)) {
3140 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3141 win_rc = WERR_ACCESS_DENIED;
3142 goto done;
3145 switch (action) {
3146 case SPOOL_DS_PUBLISH:
3147 case SPOOL_DS_UPDATE:
3148 win_rc = nt_printer_publish_ads(ads, printer);
3149 break;
3150 case SPOOL_DS_UNPUBLISH:
3151 win_rc = nt_printer_unpublish_ads(ads, printer);
3152 break;
3155 done:
3156 free_a_printer(&printer, 2);
3157 ads_destroy(&ads);
3158 return win_rc;
3161 WERROR check_published_printers(void)
3163 ADS_STATUS ads_rc;
3164 ADS_STRUCT *ads = NULL;
3165 int snum;
3166 int n_services = lp_numservices();
3167 NT_PRINTER_INFO_LEVEL *printer = NULL;
3169 ads = ads_init(NULL, NULL, NULL);
3170 if (!ads) {
3171 DEBUG(3, ("ads_init() failed\n"));
3172 return WERR_SERVER_UNAVAILABLE;
3174 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3175 SAFE_FREE(ads->auth.password);
3176 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3177 NULL, NULL);
3179 /* ads_connect() will find the DC for us */
3180 ads_rc = ads_connect(ads);
3181 if (!ADS_ERR_OK(ads_rc)) {
3182 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3183 ads_destroy(&ads);
3184 return WERR_ACCESS_DENIED;
3187 for (snum = 0; snum < n_services; snum++) {
3188 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3189 continue;
3191 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3192 lp_servicename(snum))) &&
3193 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3194 nt_printer_publish_ads(ads, printer);
3196 free_a_printer(&printer, 2);
3199 ads_destroy(&ads);
3200 return WERR_OK;
3203 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3204 struct uuid *guid)
3206 NT_PRINTER_INFO_LEVEL *printer = NULL;
3207 REGVAL_CTR *ctr;
3208 REGISTRY_VALUE *guid_val;
3209 WERROR win_rc;
3210 int i;
3212 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3214 if (!W_ERROR_IS_OK(win_rc) ||
3215 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3216 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3217 !(ctr = printer->info_2->data->keys[i].values) ||
3218 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3220 free_a_printer(&printer, 2);
3221 return False;
3224 /* fetching printer guids really ought to be a separate function.. */
3225 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3226 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3228 free_a_printer(&printer, 2);
3229 return True;
3231 #else
3232 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3234 return WERR_OK;
3237 WERROR check_published_printers(void)
3239 return WERR_OK;
3242 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3243 struct uuid *guid)
3245 return False;
3247 #endif /* HAVE_ADS */
3249 /****************************************************************************
3250 ***************************************************************************/
3252 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3254 NT_PRINTER_DATA *data;
3255 int i;
3256 int removed_keys = 0;
3257 int empty_slot;
3259 data = p2->data;
3260 empty_slot = data->num_keys;
3262 if ( !key )
3263 return WERR_INVALID_PARAM;
3265 /* remove all keys */
3267 if ( !strlen(key) ) {
3269 TALLOC_FREE( data );
3271 p2->data = NULL;
3273 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3274 p2->printername ));
3276 return WERR_OK;
3279 /* remove a specific key (and all subkeys) */
3281 for ( i=0; i<data->num_keys; i++ ) {
3282 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3283 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3284 data->keys[i].name));
3286 TALLOC_FREE( data->keys[i].name );
3287 TALLOC_FREE( data->keys[i].values );
3289 /* mark the slot as empty */
3291 ZERO_STRUCTP( &data->keys[i] );
3295 /* find the first empty slot */
3297 for ( i=0; i<data->num_keys; i++ ) {
3298 if ( !data->keys[i].name ) {
3299 empty_slot = i;
3300 removed_keys++;
3301 break;
3305 if ( i == data->num_keys )
3306 /* nothing was removed */
3307 return WERR_INVALID_PARAM;
3309 /* move everything down */
3311 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3312 if ( data->keys[i].name ) {
3313 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3314 ZERO_STRUCTP( &data->keys[i] );
3315 empty_slot++;
3316 removed_keys++;
3320 /* update count */
3322 data->num_keys -= removed_keys;
3324 /* sanity check to see if anything is left */
3326 if ( !data->num_keys ) {
3327 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3329 SAFE_FREE( data->keys );
3330 ZERO_STRUCTP( data );
3333 return WERR_OK;
3336 /****************************************************************************
3337 ***************************************************************************/
3339 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3341 WERROR result = WERR_OK;
3342 int key_index;
3344 /* we must have names on non-zero length */
3346 if ( !key || !*key|| !value || !*value )
3347 return WERR_INVALID_NAME;
3349 /* find the printer key first */
3351 key_index = lookup_printerkey( p2->data, key );
3352 if ( key_index == -1 )
3353 return WERR_OK;
3355 /* make sure the value exists so we can return the correct error code */
3357 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3358 return WERR_BADFILE;
3360 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3362 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3363 key, value ));
3365 return result;
3368 /****************************************************************************
3369 ***************************************************************************/
3371 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3372 uint32 type, uint8 *data, int real_len )
3374 WERROR result = WERR_OK;
3375 int key_index;
3377 /* we must have names on non-zero length */
3379 if ( !key || !*key|| !value || !*value )
3380 return WERR_INVALID_NAME;
3382 /* find the printer key first */
3384 key_index = lookup_printerkey( p2->data, key );
3385 if ( key_index == -1 )
3386 key_index = add_new_printer_key( p2->data, key );
3388 if ( key_index == -1 )
3389 return WERR_NOMEM;
3391 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3392 type, (const char *)data, real_len );
3394 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3395 key, value, type, real_len ));
3397 return result;
3400 /****************************************************************************
3401 ***************************************************************************/
3403 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3405 int key_index;
3407 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3408 return NULL;
3410 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3411 key, value ));
3413 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3416 /****************************************************************************
3417 Unpack a list of registry values frem the TDB
3418 ***************************************************************************/
3420 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3422 int len = 0;
3423 uint32 type;
3424 pstring string, valuename, keyname;
3425 char *str;
3426 int size;
3427 uint8 *data_p;
3428 REGISTRY_VALUE *regval_p;
3429 int key_index;
3431 /* add the "PrinterDriverData" key first for performance reasons */
3433 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3435 /* loop and unpack the rest of the registry values */
3437 while ( True ) {
3439 /* check to see if there are any more registry values */
3441 regval_p = NULL;
3442 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3443 if ( !regval_p )
3444 break;
3446 /* unpack the next regval */
3448 len += tdb_unpack(buf+len, buflen-len, "fdB",
3449 string,
3450 &type,
3451 &size,
3452 &data_p);
3454 /* lookup for subkey names which have a type of REG_NONE */
3455 /* there's no data with this entry */
3457 if ( type == REG_NONE ) {
3458 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3459 add_new_printer_key( printer_data, string );
3460 continue;
3464 * break of the keyname from the value name.
3465 * Valuenames can have embedded '\'s so be careful.
3466 * only support one level of keys. See the
3467 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3468 * -- jerry
3471 str = strchr_m( string, '\\');
3473 /* Put in "PrinterDriverData" is no key specified */
3475 if ( !str ) {
3476 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3477 pstrcpy( valuename, string );
3479 else {
3480 *str = '\0';
3481 pstrcpy( keyname, string );
3482 pstrcpy( valuename, str+1 );
3485 /* see if we need a new key */
3487 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3488 key_index = add_new_printer_key( printer_data, keyname );
3490 if ( key_index == -1 ) {
3491 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3492 keyname));
3493 break;
3496 /* add the new value */
3498 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3500 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3502 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3505 return len;
3508 /****************************************************************************
3509 ***************************************************************************/
3511 static void map_to_os2_driver(fstring drivername)
3513 static BOOL initialised=False;
3514 static fstring last_from,last_to;
3515 char *mapfile = lp_os2_driver_map();
3516 char **lines = NULL;
3517 int numlines = 0;
3518 int i;
3520 if (!strlen(drivername))
3521 return;
3523 if (!*mapfile)
3524 return;
3526 if (!initialised) {
3527 *last_from = *last_to = 0;
3528 initialised = True;
3531 if (strequal(drivername,last_from)) {
3532 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3533 fstrcpy(drivername,last_to);
3534 return;
3537 lines = file_lines_load(mapfile, &numlines,0);
3538 if (numlines == 0 || lines == NULL) {
3539 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3540 SAFE_FREE(lines);
3541 return;
3544 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3546 for( i = 0; i < numlines; i++) {
3547 char *nt_name = lines[i];
3548 char *os2_name = strchr(nt_name,'=');
3550 if (!os2_name)
3551 continue;
3553 *os2_name++ = 0;
3555 while (isspace(*nt_name))
3556 nt_name++;
3558 if (!*nt_name || strchr("#;",*nt_name))
3559 continue;
3562 int l = strlen(nt_name);
3563 while (l && isspace(nt_name[l-1])) {
3564 nt_name[l-1] = 0;
3565 l--;
3569 while (isspace(*os2_name))
3570 os2_name++;
3573 int l = strlen(os2_name);
3574 while (l && isspace(os2_name[l-1])) {
3575 os2_name[l-1] = 0;
3576 l--;
3580 if (strequal(nt_name,drivername)) {
3581 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3582 fstrcpy(last_from,drivername);
3583 fstrcpy(last_to,os2_name);
3584 fstrcpy(drivername,os2_name);
3585 file_lines_free(lines);
3586 return;
3590 file_lines_free(lines);
3593 /****************************************************************************
3594 Get a default printer info 2 struct.
3595 ****************************************************************************/
3596 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3598 int snum;
3600 snum = lp_servicenumber(sharename);
3602 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3603 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3604 servername, sharename);
3605 fstrcpy(info->sharename, sharename);
3606 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3608 /* by setting the driver name to an empty string, a local NT admin
3609 can now run the **local** APW to install a local printer driver
3610 for a Samba shared printer in 2.2. Without this, drivers **must** be
3611 installed on the Samba server for NT clients --jerry */
3612 #if 0 /* JERRY --do not uncomment-- */
3613 if (!*info->drivername)
3614 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3615 #endif
3618 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3620 pstrcpy(info->comment, "");
3621 fstrcpy(info->printprocessor, "winprint");
3622 fstrcpy(info->datatype, "RAW");
3624 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3626 info->starttime = 0; /* Minutes since 12:00am GMT */
3627 info->untiltime = 0; /* Minutes since 12:00am GMT */
3628 info->priority = 1;
3629 info->default_priority = 1;
3630 info->setuptime = (uint32)time(NULL);
3633 * I changed this as I think it is better to have a generic
3634 * DEVMODE than to crash Win2k explorer.exe --jerry
3635 * See the HP Deskjet 990c Win2k drivers for an example.
3637 * However the default devmode appears to cause problems
3638 * with the HP CLJ 8500 PCL driver. Hence the addition of
3639 * the "default devmode" parameter --jerry 22/01/2002
3642 if (lp_default_devmode(snum)) {
3643 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3644 goto fail;
3646 else {
3647 info->devmode = NULL;
3650 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3651 goto fail;
3653 return WERR_OK;
3655 fail:
3656 if (info->devmode)
3657 free_nt_devicemode(&info->devmode);
3659 return WERR_ACCESS_DENIED;
3662 /****************************************************************************
3663 ****************************************************************************/
3664 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3666 int len = 0;
3667 int snum = lp_servicenumber(sharename);
3668 TDB_DATA kbuf, dbuf;
3669 fstring printername;
3670 char adevice[MAXDEVICENAME];
3672 kbuf = make_printer_tdbkey( sharename );
3674 dbuf = tdb_fetch(tdb_printers, kbuf);
3675 if (!dbuf.dptr)
3676 return get_a_printer_2_default(info, servername, sharename);
3678 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3679 &info->attributes,
3680 &info->priority,
3681 &info->default_priority,
3682 &info->starttime,
3683 &info->untiltime,
3684 &info->status,
3685 &info->cjobs,
3686 &info->averageppm,
3687 &info->changeid,
3688 &info->c_setprinter,
3689 &info->setuptime,
3690 info->servername,
3691 info->printername,
3692 info->sharename,
3693 info->portname,
3694 info->drivername,
3695 info->comment,
3696 info->location,
3697 info->sepfile,
3698 info->printprocessor,
3699 info->datatype,
3700 info->parameters);
3702 /* Samba has to have shared raw drivers. */
3703 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3704 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3706 /* Restore the stripped strings. */
3707 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3709 if ( lp_force_printername(snum) )
3710 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3711 else
3712 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3714 fstrcpy(info->printername, printername);
3716 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3719 * Some client drivers freak out if there is a NULL devmode
3720 * (probably the driver is not checking before accessing
3721 * the devmode pointer) --jerry
3723 * See comments in get_a_printer_2_default()
3726 if (lp_default_devmode(snum) && !info->devmode) {
3727 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3728 printername));
3729 info->devmode = construct_nt_devicemode(printername);
3732 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3733 if (info->devmode) {
3734 fstrcpy(info->devmode->devicename, adevice);
3737 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3738 DEBUG(0,("unpack_values: talloc() failed!\n"));
3739 return WERR_NOMEM;
3741 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3743 /* This will get the current RPC talloc context, but we should be
3744 passing this as a parameter... fixme... JRA ! */
3746 nt_printing_getsec(info, sharename, &info->secdesc_buf);
3748 /* Fix for OS/2 drivers. */
3750 if (get_remote_arch() == RA_OS2)
3751 map_to_os2_driver(info->drivername);
3753 SAFE_FREE(dbuf.dptr);
3755 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3756 sharename, info->printername, info->drivername));
3758 return WERR_OK;
3761 /****************************************************************************
3762 Debugging function, dump at level 6 the struct in the logs.
3763 ****************************************************************************/
3764 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3766 uint32 result;
3767 NT_PRINTER_INFO_LEVEL_2 *info2;
3769 DEBUG(106,("Dumping printer at level [%d]\n", level));
3771 switch (level) {
3772 case 2:
3774 if (printer->info_2 == NULL)
3775 result=5;
3776 else
3778 info2=printer->info_2;
3780 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3781 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3782 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3783 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3784 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3785 DEBUGADD(106,("status:[%d]\n", info2->status));
3786 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3787 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3788 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3789 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3790 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3792 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3793 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3794 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3795 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3796 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3797 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3798 DEBUGADD(106,("location:[%s]\n", info2->location));
3799 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3800 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3801 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3802 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3803 result=0;
3805 break;
3807 default:
3808 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3809 result=1;
3810 break;
3813 return result;
3816 /****************************************************************************
3817 Update the changeid time.
3818 This is SO NASTY as some drivers need this to change, others need it
3819 static. This value will change every second, and I must hope that this
3820 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3821 UTAH ! JRA.
3822 ****************************************************************************/
3824 static uint32 rev_changeid(void)
3826 struct timeval tv;
3828 get_process_uptime(&tv);
3830 #if 1 /* JERRY */
3831 /* Return changeid as msec since spooler restart */
3832 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3833 #else
3835 * This setting seems to work well but is too untested
3836 * to replace the above calculation. Left in for experiementation
3837 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3839 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3840 #endif
3845 * The function below are the high level ones.
3846 * only those ones must be called from the spoolss code.
3847 * JFM.
3850 /****************************************************************************
3851 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3852 ****************************************************************************/
3854 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3856 WERROR result;
3858 dump_a_printer(printer, level);
3860 switch (level) {
3861 case 2:
3864 * Update the changestamp. Emperical tests show that the
3865 * ChangeID is always updated,but c_setprinter is
3866 * global spooler variable (not per printer).
3869 /* ChangeID **must** be increasing over the lifetime
3870 of client's spoolss service in order for the
3871 client's cache to show updates */
3873 printer->info_2->changeid = rev_changeid();
3876 * Because one day someone will ask:
3877 * NT->NT An admin connection to a remote
3878 * printer show changes imeediately in
3879 * the properities dialog
3881 * A non-admin connection will only show the
3882 * changes after viewing the properites page
3883 * 2 times. Seems to be related to a
3884 * race condition in the client between the spooler
3885 * updating the local cache and the Explorer.exe GUI
3886 * actually displaying the properties.
3888 * This is fixed in Win2k. admin/non-admin
3889 * connections both display changes immediately.
3891 * 14/12/01 --jerry
3894 result=update_a_printer_2(printer->info_2);
3896 break;
3898 default:
3899 result=WERR_UNKNOWN_LEVEL;
3900 break;
3903 return result;
3906 /****************************************************************************
3907 Initialize printer devmode & data with previously saved driver init values.
3908 ****************************************************************************/
3910 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3912 int len = 0;
3913 pstring key;
3914 TDB_DATA kbuf, dbuf;
3915 NT_PRINTER_INFO_LEVEL_2 info;
3918 ZERO_STRUCT(info);
3921 * Delete any printer data 'values' already set. When called for driver
3922 * replace, there will generally be some, but during an add printer, there
3923 * should not be any (if there are delete them).
3926 if ( info_ptr->data )
3927 delete_all_printer_data( info_ptr, "" );
3929 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3931 kbuf.dptr = key;
3932 kbuf.dsize = strlen(key)+1;
3934 dbuf = tdb_fetch(tdb_drivers, kbuf);
3935 if (!dbuf.dptr) {
3937 * When changing to a driver that has no init info in the tdb, remove
3938 * the previous drivers init info and leave the new on blank.
3940 free_nt_devicemode(&info_ptr->devmode);
3941 return False;
3945 * Get the saved DEVMODE..
3948 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3951 * The saved DEVMODE contains the devicename from the printer used during
3952 * the initialization save. Change it to reflect the new printer.
3955 if ( info.devmode ) {
3956 ZERO_STRUCT(info.devmode->devicename);
3957 fstrcpy(info.devmode->devicename, info_ptr->printername);
3961 * NT/2k does not change out the entire DeviceMode of a printer
3962 * when changing the driver. Only the driverextra, private, &
3963 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3965 * Later examination revealed that Windows NT/2k does reset the
3966 * the printer's device mode, bit **only** when you change a
3967 * property of the device mode such as the page orientation.
3968 * --jerry
3972 /* Bind the saved DEVMODE to the new the printer */
3974 free_nt_devicemode(&info_ptr->devmode);
3975 info_ptr->devmode = info.devmode;
3977 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3978 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3980 /* Add the printer data 'values' to the new printer */
3982 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3983 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3984 return False;
3987 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3990 SAFE_FREE(dbuf.dptr);
3992 return True;
3995 /****************************************************************************
3996 Initialize printer devmode & data with previously saved driver init values.
3997 When a printer is created using AddPrinter, the drivername bound to the
3998 printer is used to lookup previously saved driver initialization info, which
3999 is bound to the new printer.
4000 ****************************************************************************/
4002 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4004 BOOL result = False;
4006 switch (level) {
4007 case 2:
4008 result = set_driver_init_2(printer->info_2);
4009 break;
4011 default:
4012 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4013 level));
4014 break;
4017 return result;
4020 /****************************************************************************
4021 Delete driver init data stored for a specified driver
4022 ****************************************************************************/
4024 BOOL del_driver_init(char *drivername)
4026 pstring key;
4027 TDB_DATA kbuf;
4029 if (!drivername || !*drivername) {
4030 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4031 return False;
4034 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4036 kbuf.dptr = key;
4037 kbuf.dsize = strlen(key)+1;
4039 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4041 return (tdb_delete(tdb_drivers, kbuf) == 0);
4044 /****************************************************************************
4045 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4046 in the tdb. Note: this is different from the driver entry and the printer
4047 entry. There should be a single driver init entry for each driver regardless
4048 of whether it was installed from NT or 2K. Technically, they should be
4049 different, but they work out to the same struct.
4050 ****************************************************************************/
4052 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4054 pstring key;
4055 char *buf;
4056 int buflen, len, ret;
4057 TDB_DATA kbuf, dbuf;
4059 buf = NULL;
4060 buflen = 0;
4062 again:
4063 len = 0;
4064 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4066 len += pack_values( info->data, buf+len, buflen-len );
4068 if (buflen < len) {
4069 buf = (char *)SMB_REALLOC(buf, len);
4070 if (!buf) {
4071 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4072 ret = -1;
4073 goto done;
4075 buflen = len;
4076 goto again;
4079 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4081 kbuf.dptr = key;
4082 kbuf.dsize = strlen(key)+1;
4083 dbuf.dptr = buf;
4084 dbuf.dsize = len;
4086 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4088 done:
4089 if (ret == -1)
4090 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4092 SAFE_FREE(buf);
4094 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4095 info->sharename, info->drivername));
4097 return ret;
4100 /****************************************************************************
4101 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4102 ****************************************************************************/
4104 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4106 uint32 result;
4108 dump_a_printer(printer, level);
4110 switch (level) {
4111 case 2:
4112 result = update_driver_init_2(printer->info_2);
4113 break;
4114 default:
4115 result = 1;
4116 break;
4119 return result;
4122 /****************************************************************************
4123 Convert the printer data value, a REG_BINARY array, into an initialization
4124 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4125 got to keep the endians happy :).
4126 ****************************************************************************/
4128 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4130 BOOL result = False;
4131 prs_struct ps;
4132 DEVICEMODE devmode;
4134 ZERO_STRUCT(devmode);
4136 prs_init(&ps, 0, ctx, UNMARSHALL);
4137 ps.data_p = (char *)data;
4138 ps.buffer_size = data_len;
4140 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4141 result = convert_devicemode("", &devmode, &nt_devmode);
4142 else
4143 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4145 return result;
4148 /****************************************************************************
4149 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4151 1. Use the driver's config DLL to this UNC printername and:
4152 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4153 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4154 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4156 The last step triggers saving the "driver initialization" information for
4157 this printer into the tdb. Later, new printers that use this driver will
4158 have this initialization information bound to them. This simulates the
4159 driver initialization, as if it had run on the Samba server (as it would
4160 have done on NT).
4162 The Win32 client side code requirement sucks! But until we can run arbitrary
4163 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4165 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4166 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4167 about it and you will realize why. JRR 010720
4168 ****************************************************************************/
4170 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4172 WERROR status = WERR_OK;
4173 TALLOC_CTX *ctx = NULL;
4174 NT_DEVICEMODE *nt_devmode = NULL;
4175 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4178 * When the DEVMODE is already set on the printer, don't try to unpack it.
4180 DEBUG(8,("save_driver_init_2: Enter...\n"));
4182 if ( !printer->info_2->devmode && data_len ) {
4184 * Set devmode on printer info, so entire printer initialization can be
4185 * saved to tdb.
4188 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4189 return WERR_NOMEM;
4191 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4192 status = WERR_NOMEM;
4193 goto done;
4196 ZERO_STRUCTP(nt_devmode);
4199 * The DEVMODE is held in the 'data' component of the param in raw binary.
4200 * Convert it to to a devmode structure
4202 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4203 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4204 status = WERR_INVALID_PARAM;
4205 goto done;
4208 printer->info_2->devmode = nt_devmode;
4212 * Pack up and add (or update) the DEVMODE and any current printer data to
4213 * a 'driver init' element in the tdb
4217 if ( update_driver_init(printer, 2) != 0 ) {
4218 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4219 status = WERR_NOMEM;
4220 goto done;
4224 * If driver initialization info was successfully saved, set the current
4225 * printer to match it. This allows initialization of the current printer
4226 * as well as the driver.
4228 status = mod_a_printer(printer, 2);
4229 if (!W_ERROR_IS_OK(status)) {
4230 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4231 printer->info_2->printername));
4234 done:
4235 talloc_destroy(ctx);
4236 free_nt_devicemode( &nt_devmode );
4238 printer->info_2->devmode = tmp_devmode;
4240 return status;
4243 /****************************************************************************
4244 Update the driver init info (DEVMODE and specifics) for a printer
4245 ****************************************************************************/
4247 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4249 WERROR status = WERR_OK;
4251 switch (level) {
4252 case 2:
4253 status = save_driver_init_2( printer, data, data_len );
4254 break;
4255 default:
4256 status = WERR_UNKNOWN_LEVEL;
4257 break;
4260 return status;
4263 /****************************************************************************
4264 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4266 Previously the code had a memory allocation problem because it always
4267 used the TALLOC_CTX from the Printer_entry*. This context lasts
4268 as a long as the original handle is open. So if the client made a lot
4269 of getprinter[data]() calls, the memory usage would climb. Now we use
4270 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4271 still use the Printer_entry->ctx for maintaining the cache copy though
4272 since that object must live as long as the handle by definition.
4273 --jerry
4275 ****************************************************************************/
4277 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4278 const char *sharename)
4280 WERROR result;
4281 fstring servername;
4283 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4285 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4286 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4287 return WERR_NOMEM;
4290 switch (level) {
4291 case 2:
4292 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4293 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4294 TALLOC_FREE( *pp_printer );
4295 return WERR_NOMEM;
4298 if ( print_hnd )
4299 fstrcpy( servername, print_hnd->servername );
4300 else {
4301 fstrcpy( servername, "%L" );
4302 standard_sub_basic( "", servername, sizeof(servername)-1 );
4305 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4308 /* we have a new printer now. Save it with this handle */
4310 if ( !W_ERROR_IS_OK(result) ) {
4311 TALLOC_FREE( *pp_printer );
4312 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4313 sharename, (unsigned int)level, dos_errstr(result)));
4314 return result;
4317 dump_a_printer( *pp_printer, level);
4319 break;
4321 default:
4322 TALLOC_FREE( *pp_printer );
4323 return WERR_UNKNOWN_LEVEL;
4326 return WERR_OK;
4329 /****************************************************************************
4330 Deletes a NT_PRINTER_INFO_LEVEL struct.
4331 ****************************************************************************/
4333 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4335 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4337 if ( !printer )
4338 return 0;
4340 switch (level) {
4341 case 2:
4342 if ( printer->info_2 )
4343 free_nt_printer_info_level_2(&printer->info_2);
4344 break;
4346 default:
4347 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4348 return 1;
4351 TALLOC_FREE(*pp_printer);
4353 return 0;
4356 /****************************************************************************
4357 ****************************************************************************/
4358 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4360 uint32 result;
4361 DEBUG(104,("adding a printer at level [%d]\n", level));
4362 dump_a_printer_driver(driver, level);
4364 switch (level) {
4365 case 3:
4366 result=add_a_printer_driver_3(driver.info_3);
4367 break;
4369 case 6:
4370 result=add_a_printer_driver_6(driver.info_6);
4371 break;
4373 default:
4374 result=1;
4375 break;
4378 return result;
4380 /****************************************************************************
4381 ****************************************************************************/
4383 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4384 fstring drivername, const char *architecture, uint32 version)
4386 WERROR result;
4388 switch (level) {
4389 case 3:
4390 /* Sometime we just want any version of the driver */
4392 if ( version == DRIVER_ANY_VERSION ) {
4393 /* look for Win2k first and then for NT4 */
4394 result = get_a_printer_driver_3(&driver->info_3, drivername,
4395 architecture, 3);
4397 if ( !W_ERROR_IS_OK(result) ) {
4398 result = get_a_printer_driver_3( &driver->info_3,
4399 drivername, architecture, 2 );
4401 } else {
4402 result = get_a_printer_driver_3(&driver->info_3, drivername,
4403 architecture, version);
4405 break;
4407 default:
4408 result=W_ERROR(1);
4409 break;
4412 if (W_ERROR_IS_OK(result))
4413 dump_a_printer_driver(*driver, level);
4415 return result;
4418 /****************************************************************************
4419 ****************************************************************************/
4420 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4422 uint32 result;
4424 switch (level) {
4425 case 3:
4427 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4428 if (driver.info_3 != NULL)
4430 info3=driver.info_3;
4431 SAFE_FREE(info3->dependentfiles);
4432 ZERO_STRUCTP(info3);
4433 SAFE_FREE(info3);
4434 result=0;
4435 } else {
4436 result=4;
4438 break;
4440 case 6:
4442 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4443 if (driver.info_6 != NULL) {
4444 info6=driver.info_6;
4445 SAFE_FREE(info6->dependentfiles);
4446 SAFE_FREE(info6->previousnames);
4447 ZERO_STRUCTP(info6);
4448 SAFE_FREE(info6);
4449 result=0;
4450 } else {
4451 result=4;
4453 break;
4455 default:
4456 result=1;
4457 break;
4459 return result;
4463 /****************************************************************************
4464 Determine whether or not a particular driver is currently assigned
4465 to a printer
4466 ****************************************************************************/
4468 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4470 int snum;
4471 int n_services = lp_numservices();
4472 NT_PRINTER_INFO_LEVEL *printer = NULL;
4473 BOOL in_use = False;
4475 if ( !info_3 )
4476 return False;
4478 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4480 /* loop through the printers.tdb and check for the drivername */
4482 for (snum=0; snum<n_services && !in_use; snum++) {
4483 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4484 continue;
4486 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4487 continue;
4489 if ( strequal(info_3->name, printer->info_2->drivername) )
4490 in_use = True;
4492 free_a_printer( &printer, 2 );
4495 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4497 if ( in_use ) {
4498 NT_PRINTER_DRIVER_INFO_LEVEL d;
4499 WERROR werr;
4501 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4503 /* we can still remove the driver if there is one of
4504 "Windows NT x86" version 2 or 3 left */
4506 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4507 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4509 else {
4510 switch ( info_3->cversion ) {
4511 case 2:
4512 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4513 break;
4514 case 3:
4515 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4516 break;
4517 default:
4518 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4519 info_3->cversion));
4520 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4521 break;
4525 /* now check the error code */
4527 if ( W_ERROR_IS_OK(werr) ) {
4528 /* it's ok to remove the driver, we have other architctures left */
4529 in_use = False;
4530 free_a_printer_driver( d, 3 );
4534 /* report that the driver is not in use by default */
4536 return in_use;
4540 /**********************************************************************
4541 Check to see if a ogiven file is in use by *info
4542 *********************************************************************/
4544 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4546 int i = 0;
4548 if ( !info )
4549 return False;
4551 if ( strequal(file, info->driverpath) )
4552 return True;
4554 if ( strequal(file, info->datafile) )
4555 return True;
4557 if ( strequal(file, info->configfile) )
4558 return True;
4560 if ( strequal(file, info->helpfile) )
4561 return True;
4563 /* see of there are any dependent files to examine */
4565 if ( !info->dependentfiles )
4566 return False;
4568 while ( *info->dependentfiles[i] ) {
4569 if ( strequal(file, info->dependentfiles[i]) )
4570 return True;
4571 i++;
4574 return False;
4578 /**********************************************************************
4579 Utility function to remove the dependent file pointed to by the
4580 input parameter from the list
4581 *********************************************************************/
4583 static void trim_dependent_file( fstring files[], int idx )
4586 /* bump everything down a slot */
4588 while( *files[idx+1] ) {
4589 fstrcpy( files[idx], files[idx+1] );
4590 idx++;
4593 *files[idx] = '\0';
4595 return;
4598 /**********************************************************************
4599 Check if any of the files used by src are also used by drv
4600 *********************************************************************/
4602 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4603 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4605 BOOL in_use = False;
4606 int i = 0;
4608 if ( !src || !drv )
4609 return False;
4611 /* check each file. Remove it from the src structure if it overlaps */
4613 if ( drv_file_in_use(src->driverpath, drv) ) {
4614 in_use = True;
4615 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4616 fstrcpy( src->driverpath, "" );
4619 if ( drv_file_in_use(src->datafile, drv) ) {
4620 in_use = True;
4621 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4622 fstrcpy( src->datafile, "" );
4625 if ( drv_file_in_use(src->configfile, drv) ) {
4626 in_use = True;
4627 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4628 fstrcpy( src->configfile, "" );
4631 if ( drv_file_in_use(src->helpfile, drv) ) {
4632 in_use = True;
4633 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4634 fstrcpy( src->helpfile, "" );
4637 /* are there any dependentfiles to examine? */
4639 if ( !src->dependentfiles )
4640 return in_use;
4642 while ( *src->dependentfiles[i] ) {
4643 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4644 in_use = True;
4645 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4646 trim_dependent_file( src->dependentfiles, i );
4647 } else
4648 i++;
4651 return in_use;
4654 /****************************************************************************
4655 Determine whether or not a particular driver files are currently being
4656 used by any other driver.
4658 Return value is True if any files were in use by other drivers
4659 and False otherwise.
4661 Upon return, *info has been modified to only contain the driver files
4662 which are not in use
4663 ****************************************************************************/
4665 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4667 int i;
4668 int ndrivers;
4669 uint32 version;
4670 fstring *list = NULL;
4671 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4673 if ( !info )
4674 return False;
4676 version = info->cversion;
4678 /* loop over all driver versions */
4680 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4682 /* get the list of drivers */
4684 list = NULL;
4685 ndrivers = get_ntdrivers(&list, info->environment, version);
4687 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4688 ndrivers, info->environment, version));
4690 /* check each driver for overlap in files */
4692 for (i=0; i<ndrivers; i++) {
4693 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4695 ZERO_STRUCT(driver);
4697 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4698 SAFE_FREE(list);
4699 return True;
4702 /* check if d2 uses any files from d1 */
4703 /* only if this is a different driver than the one being deleted */
4705 if ( !strequal(info->name, driver.info_3->name) ) {
4706 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4707 free_a_printer_driver(driver, 3);
4708 SAFE_FREE( list );
4709 return True;
4713 free_a_printer_driver(driver, 3);
4716 SAFE_FREE(list);
4718 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4720 driver.info_3 = info;
4722 if ( DEBUGLEVEL >= 20 )
4723 dump_a_printer_driver( driver, 3 );
4725 return False;
4728 /****************************************************************************
4729 Actually delete the driver files. Make sure that
4730 printer_driver_files_in_use() return False before calling
4731 this.
4732 ****************************************************************************/
4734 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4736 int i = 0;
4737 char *s;
4738 pstring file;
4739 connection_struct *conn;
4740 DATA_BLOB null_pw;
4741 NTSTATUS nt_status;
4742 fstring res_type;
4743 BOOL bad_path;
4744 SMB_STRUCT_STAT st;
4746 if ( !info_3 )
4747 return False;
4749 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4752 * Connect to the print$ share under the same account as the
4753 * user connected to the rpc pipe. Note we must be root to
4754 * do this.
4757 null_pw = data_blob( NULL, 0 );
4758 fstrcpy(res_type, "A:");
4759 become_root();
4760 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4761 unbecome_root();
4763 if ( !conn ) {
4764 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4765 return False;
4768 if ( !CAN_WRITE(conn) ) {
4769 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4770 return False;
4773 /* Save who we are - we are temporarily becoming the connection user. */
4775 if ( !become_user(conn, conn->vuid) ) {
4776 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4777 return False;
4780 /* now delete the files; must strip the '\print$' string from
4781 fron of path */
4783 if ( *info_3->driverpath ) {
4784 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4785 pstrcpy( file, s );
4786 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4787 DEBUG(10,("deleting driverfile [%s]\n", s));
4788 unlink_internals(conn, 0, file, False);
4792 if ( *info_3->configfile ) {
4793 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4794 pstrcpy( file, s );
4795 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4796 DEBUG(10,("deleting configfile [%s]\n", s));
4797 unlink_internals(conn, 0, file, False);
4801 if ( *info_3->datafile ) {
4802 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4803 pstrcpy( file, s );
4804 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4805 DEBUG(10,("deleting datafile [%s]\n", s));
4806 unlink_internals(conn, 0, file, False);
4810 if ( *info_3->helpfile ) {
4811 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4812 pstrcpy( file, s );
4813 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4814 DEBUG(10,("deleting helpfile [%s]\n", s));
4815 unlink_internals(conn, 0, file, False);
4819 /* check if we are done removing files */
4821 if ( info_3->dependentfiles ) {
4822 while ( info_3->dependentfiles[i][0] ) {
4823 char *p;
4825 /* bypass the "\print$" portion of the path */
4827 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4828 pstrcpy( file, p );
4829 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4830 DEBUG(10,("deleting dependent file [%s]\n", file));
4831 unlink_internals(conn, 0, file, False);
4834 i++;
4838 unbecome_user();
4840 return True;
4843 /****************************************************************************
4844 Remove a printer driver from the TDB. This assumes that the the driver was
4845 previously looked up.
4846 ***************************************************************************/
4848 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4849 uint32 version, BOOL delete_files )
4851 pstring key;
4852 const char *arch;
4853 TDB_DATA kbuf, dbuf;
4854 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4856 /* delete the tdb data first */
4858 arch = get_short_archi(info_3->environment);
4859 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4860 arch, version, info_3->name);
4862 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4863 key, delete_files ? "TRUE" : "FALSE" ));
4865 ctr.info_3 = info_3;
4866 dump_a_printer_driver( ctr, 3 );
4868 kbuf.dptr=key;
4869 kbuf.dsize=strlen(key)+1;
4871 /* check if the driver actually exists for this environment */
4873 dbuf = tdb_fetch( tdb_drivers, kbuf );
4874 if ( !dbuf.dptr ) {
4875 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4876 return WERR_UNKNOWN_PRINTER_DRIVER;
4879 SAFE_FREE( dbuf.dptr );
4881 /* ok... the driver exists so the delete should return success */
4883 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4884 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4885 return WERR_ACCESS_DENIED;
4889 * now delete any associated files if delete_files == True
4890 * even if this part failes, we return succes because the
4891 * driver doesn not exist any more
4894 if ( delete_files )
4895 delete_driver_files( info_3, user );
4898 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4900 return WERR_OK;
4903 /****************************************************************************
4904 Store a security desc for a printer.
4905 ****************************************************************************/
4907 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4909 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4910 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4911 prs_struct ps;
4912 TALLOC_CTX *mem_ctx = NULL;
4913 char *key;
4914 WERROR status;
4916 mem_ctx = talloc_init("nt_printing_setsec");
4917 if (mem_ctx == NULL)
4918 return WERR_NOMEM;
4920 /* The old owner and group sids of the security descriptor are not
4921 present when new ACEs are added or removed by changing printer
4922 permissions through NT. If they are NULL in the new security
4923 descriptor then copy them over from the old one. */
4925 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4926 DOM_SID *owner_sid, *group_sid;
4927 SEC_ACL *dacl, *sacl;
4928 SEC_DESC *psd = NULL;
4929 size_t size;
4931 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4933 /* Pick out correct owner and group sids */
4935 owner_sid = secdesc_ctr->sec->owner_sid ?
4936 secdesc_ctr->sec->owner_sid :
4937 old_secdesc_ctr->sec->owner_sid;
4939 group_sid = secdesc_ctr->sec->grp_sid ?
4940 secdesc_ctr->sec->grp_sid :
4941 old_secdesc_ctr->sec->grp_sid;
4943 dacl = secdesc_ctr->sec->dacl ?
4944 secdesc_ctr->sec->dacl :
4945 old_secdesc_ctr->sec->dacl;
4947 sacl = secdesc_ctr->sec->sacl ?
4948 secdesc_ctr->sec->sacl :
4949 old_secdesc_ctr->sec->sacl;
4951 /* Make a deep copy of the security descriptor */
4953 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4954 owner_sid, group_sid,
4955 sacl,
4956 dacl,
4957 &size);
4959 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4962 if (!new_secdesc_ctr) {
4963 new_secdesc_ctr = secdesc_ctr;
4966 /* Store the security descriptor in a tdb */
4968 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4969 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4971 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4972 &ps, 1)) {
4973 status = WERR_BADFUNC;
4974 goto out;
4977 key = make_printers_secdesc_tdbkey( sharename );
4979 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4980 status = WERR_OK;
4981 } else {
4982 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4983 status = WERR_BADFUNC;
4986 /* Free malloc'ed memory */
4988 out:
4990 prs_mem_free(&ps);
4991 if (mem_ctx)
4992 talloc_destroy(mem_ctx);
4993 return status;
4996 /****************************************************************************
4997 Construct a default security descriptor buffer for a printer.
4998 ****************************************************************************/
5000 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5002 SEC_ACE ace[5]; /* max number of ace entries */
5003 int i = 0;
5004 SEC_ACCESS sa;
5005 SEC_ACL *psa = NULL;
5006 SEC_DESC_BUF *sdb = NULL;
5007 SEC_DESC *psd = NULL;
5008 DOM_SID adm_sid;
5009 size_t sd_size;
5011 /* Create an ACE where Everyone is allowed to print */
5013 init_sec_access(&sa, PRINTER_ACE_PRINT);
5014 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5015 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5017 /* Add the domain admins group if we are a DC */
5019 if ( IS_DC ) {
5020 DOM_SID domadmins_sid;
5022 sid_copy(&domadmins_sid, get_global_sam_sid());
5023 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5025 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5026 init_sec_ace(&ace[i++], &domadmins_sid,
5027 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5028 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5029 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5030 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5032 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5033 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5035 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5036 init_sec_ace(&ace[i++], &adm_sid,
5037 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5038 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5039 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5040 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5043 /* add BUILTIN\Administrators as FULL CONTROL */
5045 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5046 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5047 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5048 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5049 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5050 SEC_ACE_TYPE_ACCESS_ALLOWED,
5051 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5053 /* Make the security descriptor owned by the BUILTIN\Administrators */
5055 /* The ACL revision number in rpc_secdesc.h differs from the one
5056 created by NT when setting ACE entries in printer
5057 descriptors. NT4 complains about the property being edited by a
5058 NT5 machine. */
5060 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5061 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5062 &global_sid_Builtin_Administrators,
5063 &global_sid_Builtin_Administrators,
5064 NULL, psa, &sd_size);
5067 if (!psd) {
5068 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5069 return NULL;
5072 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5074 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5075 (unsigned int)sd_size));
5077 return sdb;
5080 /****************************************************************************
5081 Get a security desc for a printer.
5082 ****************************************************************************/
5084 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5086 prs_struct ps;
5087 char *key;
5088 char *temp;
5090 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5091 sharename = temp + 1;
5094 /* Fetch security descriptor from tdb */
5096 key = make_printers_secdesc_tdbkey( sharename );
5098 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5099 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5101 DEBUG(4,("using default secdesc for %s\n", sharename));
5103 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5104 return False;
5107 /* Save default security descriptor for later */
5109 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5110 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5112 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5113 tdb_prs_store(tdb_printers, key, &ps);
5115 prs_mem_free(&ps);
5117 return True;
5120 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5121 this security descriptor has been created when winbindd was
5122 down. Take ownership of security descriptor. */
5124 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5125 DOM_SID owner_sid;
5127 /* Change sd owner to workgroup administrator */
5129 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5130 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5131 SEC_DESC *psd = NULL;
5132 size_t size;
5134 /* Create new sd */
5136 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5138 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5139 &owner_sid,
5140 (*secdesc_ctr)->sec->grp_sid,
5141 (*secdesc_ctr)->sec->sacl,
5142 (*secdesc_ctr)->sec->dacl,
5143 &size);
5145 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5147 /* Swap with other one */
5149 *secdesc_ctr = new_secdesc_ctr;
5151 /* Set it */
5153 nt_printing_setsec(sharename, *secdesc_ctr);
5157 if (DEBUGLEVEL >= 10) {
5158 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5159 int i;
5161 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5162 sharename, the_acl->num_aces));
5164 for (i = 0; i < the_acl->num_aces; i++) {
5165 fstring sid_str;
5167 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5169 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5170 the_acl->ace[i].type, the_acl->ace[i].flags,
5171 the_acl->ace[i].info.mask));
5175 prs_mem_free(&ps);
5176 return True;
5179 /* error code:
5180 0: everything OK
5181 1: level not implemented
5182 2: file doesn't exist
5183 3: can't allocate memory
5184 4: can't free memory
5185 5: non existant struct
5189 A printer and a printer driver are 2 different things.
5190 NT manages them separatelly, Samba does the same.
5191 Why ? Simply because it's easier and it makes sense !
5193 Now explanation: You have 3 printers behind your samba server,
5194 2 of them are the same make and model (laser A and B). But laser B
5195 has an 3000 sheet feeder and laser A doesn't such an option.
5196 Your third printer is an old dot-matrix model for the accounting :-).
5198 If the /usr/local/samba/lib directory (default dir), you will have
5199 5 files to describe all of this.
5201 3 files for the printers (1 by printer):
5202 NTprinter_laser A
5203 NTprinter_laser B
5204 NTprinter_accounting
5205 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5206 NTdriver_printer model X
5207 NTdriver_printer model Y
5209 jfm: I should use this comment for the text file to explain
5210 same thing for the forms BTW.
5211 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5215 /* Convert generic access rights to printer object specific access rights.
5216 It turns out that NT4 security descriptors use generic access rights and
5217 NT5 the object specific ones. */
5219 void map_printer_permissions(SEC_DESC *sd)
5221 int i;
5223 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5224 se_map_generic(&sd->dacl->ace[i].info.mask,
5225 &printer_generic_mapping);
5229 /****************************************************************************
5230 Check a user has permissions to perform the given operation. We use the
5231 permission constants defined in include/rpc_spoolss.h to check the various
5232 actions we perform when checking printer access.
5234 PRINTER_ACCESS_ADMINISTER:
5235 print_queue_pause, print_queue_resume, update_printer_sec,
5236 update_printer, spoolss_addprinterex_level_2,
5237 _spoolss_setprinterdata
5239 PRINTER_ACCESS_USE:
5240 print_job_start
5242 JOB_ACCESS_ADMINISTER:
5243 print_job_delete, print_job_pause, print_job_resume,
5244 print_queue_purge
5246 Try access control in the following order (for performance reasons):
5247 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5248 2) check security descriptor (bit comparisons in memory)
5249 3) "printer admins" (may result in numerous calls to winbind)
5251 ****************************************************************************/
5252 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5254 SEC_DESC_BUF *secdesc = NULL;
5255 uint32 access_granted;
5256 NTSTATUS status;
5257 BOOL result;
5258 const char *pname;
5259 TALLOC_CTX *mem_ctx = NULL;
5260 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5262 /* If user is NULL then use the current_user structure */
5264 if (!user)
5265 user = &current_user;
5267 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5269 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5270 return True;
5273 /* Get printer name */
5275 pname = PRINTERNAME(snum);
5277 if (!pname || !*pname) {
5278 errno = EACCES;
5279 return False;
5282 /* Get printer security descriptor */
5284 if(!(mem_ctx = talloc_init("print_access_check"))) {
5285 errno = ENOMEM;
5286 return False;
5289 nt_printing_getsec(mem_ctx, pname, &secdesc);
5291 if (access_type == JOB_ACCESS_ADMINISTER) {
5292 SEC_DESC_BUF *parent_secdesc = secdesc;
5294 /* Create a child security descriptor to check permissions
5295 against. This is because print jobs are child objects
5296 objects of a printer. */
5298 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5300 /* Now this is the bit that really confuses me. The access
5301 type needs to be changed from JOB_ACCESS_ADMINISTER to
5302 PRINTER_ACCESS_ADMINISTER for this to work. Something
5303 to do with the child (job) object becoming like a
5304 printer?? -tpot */
5306 access_type = PRINTER_ACCESS_ADMINISTER;
5309 /* Check access */
5311 map_printer_permissions(secdesc->sec);
5313 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5314 &access_granted, &status);
5316 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5318 /* see if we need to try the printer admin list */
5320 if ((access_granted == 0) &&
5321 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5322 user->nt_user_token,
5323 lp_printer_admin(snum)))) {
5324 return True;
5327 talloc_destroy(mem_ctx);
5329 if (!result)
5330 errno = EACCES;
5332 return result;
5335 /****************************************************************************
5336 Check the time parameters allow a print operation.
5337 *****************************************************************************/
5339 BOOL print_time_access_check(int snum)
5341 NT_PRINTER_INFO_LEVEL *printer = NULL;
5342 BOOL ok = False;
5343 time_t now = time(NULL);
5344 struct tm *t;
5345 uint32 mins;
5347 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5348 return False;
5350 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5351 ok = True;
5353 t = gmtime(&now);
5354 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5356 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5357 ok = True;
5359 free_a_printer(&printer, 2);
5361 if (!ok)
5362 errno = EACCES;
5364 return ok;
5367 /****************************************************************************
5368 Fill in the servername sent in the _spoolss_open_printer_ex() call
5369 ****************************************************************************/
5371 char* get_server_name( Printer_entry *printer )
5373 return printer->servername;