r10391: * setting version to 3.0.20a
[Samba.git] / source / printing / nt_printing.c
blob7260cb3a5818f1b92faa57d8708f374a8ab3e105
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 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
622 * register callback to handle invalidating the printer cache
623 * between smbd processes.
626 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
627 #endif
629 /* of course, none of the message callbacks matter if you don't
630 tell messages.c that you interested in receiving PRINT_GENERAL
631 msgs. This is done in claim_connection() */
634 if ( lp_security() == SEC_ADS ) {
635 win_rc = check_published_printers();
636 if (!W_ERROR_IS_OK(win_rc))
637 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
640 return True;
643 /*******************************************************************
644 Function to allow filename parsing "the old way".
645 ********************************************************************/
647 static BOOL driver_unix_convert(char *name,connection_struct *conn,
648 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
650 unix_format(name);
651 unix_clean_name(name);
652 trim_string(name,"/","/");
653 return unix_convert(name, conn, saved_last_component, bad_path, pst);
656 /*******************************************************************
657 tdb traversal function for counting printers.
658 ********************************************************************/
660 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
661 TDB_DATA data, void *context)
663 int *printer_count = (int*)context;
665 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
666 (*printer_count)++;
667 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
670 return 0;
673 /*******************************************************************
674 Update the spooler global c_setprinter. This variable is initialized
675 when the parent smbd starts with the number of existing printers. It
676 is monotonically increased by the current number of printers *after*
677 each add or delete printer RPC. Only Microsoft knows why... JRR020119
678 ********************************************************************/
680 uint32 update_c_setprinter(BOOL initialize)
682 int32 c_setprinter;
683 int32 printer_count = 0;
685 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
687 /* Traverse the tdb, counting the printers */
688 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
690 /* If initializing, set c_setprinter to current printers count
691 * otherwise, bump it by the current printer count
693 if (!initialize)
694 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
695 else
696 c_setprinter = printer_count;
698 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
699 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
701 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
703 return (uint32)c_setprinter;
706 /*******************************************************************
707 Get the spooler global c_setprinter, accounting for initialization.
708 ********************************************************************/
710 uint32 get_c_setprinter(void)
712 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
714 if (c_setprinter == (int32)-1)
715 c_setprinter = update_c_setprinter(True);
717 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
719 return (uint32)c_setprinter;
722 /****************************************************************************
723 Get builtin form struct list.
724 ****************************************************************************/
726 int get_builtin_ntforms(nt_forms_struct **list)
728 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
729 return sizeof(default_forms) / sizeof(default_forms[0]);
732 /****************************************************************************
733 get a builtin form struct
734 ****************************************************************************/
736 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
738 int i,count;
739 fstring form_name;
740 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
741 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
742 count = sizeof(default_forms) / sizeof(default_forms[0]);
743 for (i=0;i<count;i++) {
744 if (strequal(form_name,default_forms[i].name)) {
745 DEBUGADD(6,("Found builtin form %s \n", form_name));
746 memcpy(form,&default_forms[i],sizeof(*form));
747 break;
751 return (i !=count);
754 /****************************************************************************
755 get a form struct list
756 ****************************************************************************/
757 int get_ntforms(nt_forms_struct **list)
759 TDB_DATA kbuf, newkey, dbuf;
760 nt_forms_struct *tl;
761 nt_forms_struct form;
762 int ret;
763 int i;
764 int n = 0;
766 for (kbuf = tdb_firstkey(tdb_forms);
767 kbuf.dptr;
768 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
770 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
771 continue;
773 dbuf = tdb_fetch(tdb_forms, kbuf);
774 if (!dbuf.dptr)
775 continue;
777 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
778 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
779 &i, &form.flag, &form.width, &form.length, &form.left,
780 &form.top, &form.right, &form.bottom);
781 SAFE_FREE(dbuf.dptr);
782 if (ret != dbuf.dsize)
783 continue;
785 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
786 if (!tl) {
787 DEBUG(0,("get_ntforms: Realloc fail.\n"));
788 return 0;
790 *list = tl;
791 (*list)[n] = form;
792 n++;
796 return n;
799 /****************************************************************************
800 write a form struct list
801 ****************************************************************************/
802 int write_ntforms(nt_forms_struct **list, int number)
804 pstring buf, key;
805 int len;
806 TDB_DATA kbuf,dbuf;
807 int i;
809 for (i=0;i<number;i++) {
810 /* save index, so list is rebuilt in correct order */
811 len = tdb_pack(buf, sizeof(buf), "dddddddd",
812 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
813 (*list)[i].left, (*list)[i].top, (*list)[i].right,
814 (*list)[i].bottom);
815 if (len > sizeof(buf)) break;
816 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
817 kbuf.dsize = strlen(key)+1;
818 kbuf.dptr = key;
819 dbuf.dsize = len;
820 dbuf.dptr = buf;
821 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
824 return i;
827 /****************************************************************************
828 add a form struct at the end of the list
829 ****************************************************************************/
830 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
832 int n=0;
833 BOOL update;
834 fstring form_name;
835 nt_forms_struct *tl;
838 * NT tries to add forms even when
839 * they are already in the base
840 * only update the values if already present
843 update=False;
845 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
846 for (n=0; n<*count; n++) {
847 if ( strequal((*list)[n].name, form_name) ) {
848 update=True;
849 break;
853 if (update==False) {
854 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
855 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
856 return False;
858 *list = tl;
859 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
860 (*count)++;
863 (*list)[n].flag=form->flags;
864 (*list)[n].width=form->size_x;
865 (*list)[n].length=form->size_y;
866 (*list)[n].left=form->left;
867 (*list)[n].top=form->top;
868 (*list)[n].right=form->right;
869 (*list)[n].bottom=form->bottom;
871 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
872 update ? "updated" : "added", form_name));
874 return True;
877 /****************************************************************************
878 Delete a named form struct.
879 ****************************************************************************/
881 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
883 pstring key;
884 TDB_DATA kbuf;
885 int n=0;
886 fstring form_name;
888 *ret = WERR_OK;
890 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
892 for (n=0; n<*count; n++) {
893 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
894 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
895 break;
899 if (n == *count) {
900 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
901 *ret = WERR_INVALID_PARAM;
902 return False;
905 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
906 kbuf.dsize = strlen(key)+1;
907 kbuf.dptr = key;
908 if (tdb_delete(tdb_forms, kbuf) != 0) {
909 *ret = WERR_NOMEM;
910 return False;
913 return True;
916 /****************************************************************************
917 Update a form struct.
918 ****************************************************************************/
920 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
922 int n=0;
923 fstring form_name;
924 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
926 DEBUG(106, ("[%s]\n", form_name));
927 for (n=0; n<count; n++) {
928 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
929 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
930 break;
933 if (n==count) return;
935 (*list)[n].flag=form->flags;
936 (*list)[n].width=form->size_x;
937 (*list)[n].length=form->size_y;
938 (*list)[n].left=form->left;
939 (*list)[n].top=form->top;
940 (*list)[n].right=form->right;
941 (*list)[n].bottom=form->bottom;
944 /****************************************************************************
945 Get the nt drivers list.
946 Traverse the database and look-up the matching names.
947 ****************************************************************************/
948 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
950 int total=0;
951 const char *short_archi;
952 fstring *fl;
953 pstring key;
954 TDB_DATA kbuf, newkey;
956 short_archi = get_short_archi(architecture);
957 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
959 for (kbuf = tdb_firstkey(tdb_drivers);
960 kbuf.dptr;
961 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
963 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
964 continue;
966 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
967 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
968 return -1;
970 else *list = fl;
972 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
973 total++;
976 return(total);
979 /****************************************************************************
980 function to do the mapping between the long architecture name and
981 the short one.
982 ****************************************************************************/
983 const char *get_short_archi(const char *long_archi)
985 int i=-1;
987 DEBUG(107,("Getting architecture dependant directory\n"));
988 do {
989 i++;
990 } while ( (archi_table[i].long_archi!=NULL ) &&
991 StrCaseCmp(long_archi, archi_table[i].long_archi) );
993 if (archi_table[i].long_archi==NULL) {
994 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
995 return NULL;
998 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1001 DEBUGADD(108,("index: [%d]\n", i));
1002 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1003 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1005 return archi_table[i].short_archi;
1008 /****************************************************************************
1009 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1010 There are two case to be covered here: PE (Portable Executable) and NE (New
1011 Executable) files. Both files support the same INFO structure, but PE files
1012 store the signature in unicode, and NE files store it as !unicode.
1013 returns -1 on error, 1 on version info found, and 0 on no version info found.
1014 ****************************************************************************/
1016 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1018 int i;
1019 char *buf = NULL;
1020 ssize_t byte_count;
1022 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1023 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1024 fname, PE_HEADER_SIZE));
1025 goto error_exit;
1028 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1029 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1030 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1031 fname, (unsigned long)byte_count));
1032 goto no_version_info;
1035 /* Is this really a DOS header? */
1036 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1037 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1038 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1039 goto no_version_info;
1042 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1043 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1044 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1045 fname, errno));
1046 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1047 goto no_version_info;
1050 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1051 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1052 fname, (unsigned long)byte_count));
1053 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1054 goto no_version_info;
1057 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1058 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1059 unsigned int num_sections;
1060 unsigned int section_table_bytes;
1062 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1063 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1064 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1065 /* At this point, we assume the file is in error. It still could be somthing
1066 * else besides a PE file, but it unlikely at this point.
1068 goto error_exit;
1071 /* get the section table */
1072 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1073 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1074 if (section_table_bytes == 0)
1075 goto error_exit;
1077 SAFE_FREE(buf);
1078 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
1079 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1080 fname, section_table_bytes));
1081 goto error_exit;
1084 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1085 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1086 fname, (unsigned long)byte_count));
1087 goto error_exit;
1090 /* Iterate the section table looking for the resource section ".rsrc" */
1091 for (i = 0; i < num_sections; i++) {
1092 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1094 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1095 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1096 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1098 if (section_bytes == 0)
1099 goto error_exit;
1101 SAFE_FREE(buf);
1102 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
1103 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1104 fname, section_bytes));
1105 goto error_exit;
1108 /* Seek to the start of the .rsrc section info */
1109 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1110 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1111 fname, errno));
1112 goto error_exit;
1115 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1116 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1117 fname, (unsigned long)byte_count));
1118 goto error_exit;
1121 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1122 goto error_exit;
1124 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1125 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1126 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1127 /* Align to next long address */
1128 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1130 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1131 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1132 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1134 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1135 fname, *major, *minor,
1136 (*major>>16)&0xffff, *major&0xffff,
1137 (*minor>>16)&0xffff, *minor&0xffff));
1138 SAFE_FREE(buf);
1139 return 1;
1146 /* Version info not found, fall back to origin date/time */
1147 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1148 SAFE_FREE(buf);
1149 return 0;
1151 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1152 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1153 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1154 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1155 /* At this point, we assume the file is in error. It still could be somthing
1156 * else besides a NE file, but it unlikely at this point. */
1157 goto error_exit;
1160 /* Allocate a bit more space to speed up things */
1161 SAFE_FREE(buf);
1162 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1163 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1164 fname, PE_HEADER_SIZE));
1165 goto error_exit;
1168 /* This is a HACK! I got tired of trying to sort through the messy
1169 * 'NE' file format. If anyone wants to clean this up please have at
1170 * it, but this works. 'NE' files will eventually fade away. JRR */
1171 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1172 /* Cover case that should not occur in a well formed 'NE' .dll file */
1173 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1175 for(i=0; i<byte_count; i++) {
1176 /* Fast skip past data that can't possibly match */
1177 if (buf[i] != 'V') continue;
1179 /* Potential match data crosses buf boundry, move it to beginning
1180 * of buf, and fill the buf with as much as it will hold. */
1181 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1182 int bc;
1184 memcpy(buf, &buf[i], byte_count-i);
1185 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1186 (byte_count-i))) < 0) {
1188 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1189 fname, errno));
1190 goto error_exit;
1193 byte_count = bc + (byte_count - i);
1194 if (byte_count<VS_VERSION_INFO_SIZE) break;
1196 i = 0;
1199 /* Check that the full signature string and the magic number that
1200 * follows exist (not a perfect solution, but the chances that this
1201 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1202 * twice, as it is simpler to read the code. */
1203 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1204 /* Compute skip alignment to next long address */
1205 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1206 sizeof(VS_SIGNATURE)) & 3;
1207 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1209 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1210 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1211 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1212 fname, *major, *minor,
1213 (*major>>16)&0xffff, *major&0xffff,
1214 (*minor>>16)&0xffff, *minor&0xffff));
1215 SAFE_FREE(buf);
1216 return 1;
1221 /* Version info not found, fall back to origin date/time */
1222 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1223 SAFE_FREE(buf);
1224 return 0;
1226 } else
1227 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1228 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1229 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1231 no_version_info:
1232 SAFE_FREE(buf);
1233 return 0;
1235 error_exit:
1236 SAFE_FREE(buf);
1237 return -1;
1240 /****************************************************************************
1241 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1242 share one or more files. During the MS installation process files are checked
1243 to insure that only a newer version of a shared file is installed over an
1244 older version. There are several possibilities for this comparison. If there
1245 is no previous version, the new one is newer (obviously). If either file is
1246 missing the version info structure, compare the creation date (on Unix use
1247 the modification date). Otherwise chose the numerically larger version number.
1248 ****************************************************************************/
1250 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1252 BOOL use_version = True;
1253 pstring filepath;
1255 uint32 new_major;
1256 uint32 new_minor;
1257 time_t new_create_time;
1259 uint32 old_major;
1260 uint32 old_minor;
1261 time_t old_create_time;
1263 files_struct *fsp = NULL;
1264 SMB_STRUCT_STAT st;
1265 SMB_STRUCT_STAT stat_buf;
1266 BOOL bad_path;
1268 SET_STAT_INVALID(st);
1269 SET_STAT_INVALID(stat_buf);
1270 new_create_time = (time_t)0;
1271 old_create_time = (time_t)0;
1273 /* Get file version info (if available) for previous file (if it exists) */
1274 pstrcpy(filepath, old_file);
1276 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1278 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1279 FILE_GENERIC_READ,
1280 FILE_SHARE_READ|FILE_SHARE_WRITE,
1281 FILE_OPEN,
1283 FILE_ATTRIBUTE_NORMAL,
1284 INTERNAL_OPEN_ONLY,
1285 NULL);
1287 if (!fsp) {
1288 /* Old file not found, so by definition new file is in fact newer */
1289 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1290 filepath, errno));
1291 return True;
1293 } else {
1294 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1295 if (ret == -1) {
1296 goto error_exit;
1299 if (!ret) {
1300 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1301 old_file));
1302 use_version = False;
1303 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1304 old_create_time = st.st_mtime;
1305 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1308 close_file(fsp, True);
1310 /* Get file version info (if available) for new file */
1311 pstrcpy(filepath, new_file);
1312 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1314 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1315 FILE_GENERIC_READ,
1316 FILE_SHARE_READ|FILE_SHARE_WRITE,
1317 FILE_OPEN,
1319 FILE_ATTRIBUTE_NORMAL,
1320 INTERNAL_OPEN_ONLY,
1321 NULL);
1323 if (!fsp) {
1324 /* New file not found, this shouldn't occur if the caller did its job */
1325 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1326 filepath, errno));
1327 goto error_exit;
1329 } else {
1330 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1331 if (ret == -1) {
1332 goto error_exit;
1335 if (!ret) {
1336 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1337 new_file));
1338 use_version = False;
1339 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1340 new_create_time = st.st_mtime;
1341 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1344 close_file(fsp, True);
1346 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1347 /* Compare versions and choose the larger version number */
1348 if (new_major > old_major ||
1349 (new_major == old_major && new_minor > old_minor)) {
1351 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1352 return True;
1354 else {
1355 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1356 return False;
1359 } else {
1360 /* Compare modification time/dates and choose the newest time/date */
1361 if (new_create_time > old_create_time) {
1362 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1363 return True;
1365 else {
1366 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1367 return False;
1371 error_exit:
1372 if(fsp)
1373 close_file(fsp, True);
1374 return -1;
1377 /****************************************************************************
1378 Determine the correct cVersion associated with an architecture and driver
1379 ****************************************************************************/
1380 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1381 struct current_user *user, WERROR *perr)
1383 int cversion;
1384 NTSTATUS nt_status;
1385 pstring driverpath;
1386 DATA_BLOB null_pw;
1387 fstring res_type;
1388 files_struct *fsp = NULL;
1389 BOOL bad_path;
1390 SMB_STRUCT_STAT st;
1391 connection_struct *conn;
1393 SET_STAT_INVALID(st);
1395 *perr = WERR_INVALID_PARAM;
1397 /* If architecture is Windows 95/98/ME, the version is always 0. */
1398 if (strcmp(architecture, "WIN40") == 0) {
1399 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1400 *perr = WERR_OK;
1401 return 0;
1405 * Connect to the print$ share under the same account as the user connected
1406 * to the rpc pipe. Note we must still be root to do this.
1409 /* Null password is ok - we are already an authenticated user... */
1410 null_pw = data_blob(NULL, 0);
1411 fstrcpy(res_type, "A:");
1412 become_root();
1413 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1414 unbecome_root();
1416 if (conn == NULL) {
1417 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1418 *perr = ntstatus_to_werror(nt_status);
1419 return -1;
1422 /* We are temporarily becoming the connection user. */
1423 if (!become_user(conn, user->vuid)) {
1424 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1425 *perr = WERR_ACCESS_DENIED;
1426 return -1;
1429 /* Open the driver file (Portable Executable format) and determine the
1430 * deriver the cversion. */
1431 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1433 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1435 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1436 *perr = WERR_BADFILE;
1437 goto error_exit;
1440 fsp = open_file_ntcreate(conn, driverpath, &st,
1441 FILE_GENERIC_READ,
1442 FILE_SHARE_READ|FILE_SHARE_WRITE,
1443 FILE_OPEN,
1445 FILE_ATTRIBUTE_NORMAL,
1446 INTERNAL_OPEN_ONLY,
1447 NULL);
1449 if (!fsp) {
1450 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1451 driverpath, errno));
1452 *perr = WERR_ACCESS_DENIED;
1453 goto error_exit;
1454 } else {
1455 uint32 major;
1456 uint32 minor;
1457 int ret = get_file_version(fsp, driverpath, &major, &minor);
1458 if (ret == -1) goto error_exit;
1460 if (!ret) {
1461 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1462 goto error_exit;
1466 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1467 * for more details. Version in this case is not just the version of the
1468 * file, but the version in the sense of kernal mode (2) vs. user mode
1469 * (3) drivers. Other bits of the version fields are the version info.
1470 * JRR 010716
1472 cversion = major & 0x0000ffff;
1473 switch (cversion) {
1474 case 2: /* WinNT drivers */
1475 case 3: /* Win2K drivers */
1476 break;
1478 default:
1479 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1480 driverpath, cversion));
1481 goto error_exit;
1484 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1485 driverpath, major, minor));
1488 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1489 driverpath, cversion));
1491 close_file(fsp, True);
1492 close_cnum(conn, user->vuid);
1493 unbecome_user();
1494 *perr = WERR_OK;
1495 return cversion;
1498 error_exit:
1500 if(fsp)
1501 close_file(fsp, True);
1503 close_cnum(conn, user->vuid);
1504 unbecome_user();
1505 return -1;
1508 /****************************************************************************
1509 ****************************************************************************/
1510 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1511 struct current_user *user)
1513 const char *architecture;
1514 fstring new_name;
1515 char *p;
1516 int i;
1517 WERROR err;
1519 /* clean up the driver name.
1520 * we can get .\driver.dll
1521 * or worse c:\windows\system\driver.dll !
1523 /* using an intermediate string to not have overlaping memcpy()'s */
1524 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1525 fstrcpy(new_name, p+1);
1526 fstrcpy(driver->driverpath, new_name);
1529 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1530 fstrcpy(new_name, p+1);
1531 fstrcpy(driver->datafile, new_name);
1534 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1535 fstrcpy(new_name, p+1);
1536 fstrcpy(driver->configfile, new_name);
1539 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1540 fstrcpy(new_name, p+1);
1541 fstrcpy(driver->helpfile, new_name);
1544 if (driver->dependentfiles) {
1545 for (i=0; *driver->dependentfiles[i]; i++) {
1546 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1547 fstrcpy(new_name, p+1);
1548 fstrcpy(driver->dependentfiles[i], new_name);
1553 architecture = get_short_archi(driver->environment);
1555 /* jfm:7/16/2000 the client always sends the cversion=0.
1556 * The server should check which version the driver is by reading
1557 * the PE header of driver->driverpath.
1559 * For Windows 95/98 the version is 0 (so the value sent is correct)
1560 * For Windows NT (the architecture doesn't matter)
1561 * NT 3.1: cversion=0
1562 * NT 3.5/3.51: cversion=1
1563 * NT 4: cversion=2
1564 * NT2K: cversion=3
1566 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1567 return err;
1569 return WERR_OK;
1572 /****************************************************************************
1573 ****************************************************************************/
1574 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1576 const char *architecture;
1577 fstring new_name;
1578 char *p;
1579 int i;
1580 WERROR err;
1582 /* clean up the driver name.
1583 * we can get .\driver.dll
1584 * or worse c:\windows\system\driver.dll !
1586 /* using an intermediate string to not have overlaping memcpy()'s */
1587 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1588 fstrcpy(new_name, p+1);
1589 fstrcpy(driver->driverpath, new_name);
1592 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1593 fstrcpy(new_name, p+1);
1594 fstrcpy(driver->datafile, new_name);
1597 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1598 fstrcpy(new_name, p+1);
1599 fstrcpy(driver->configfile, new_name);
1602 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1603 fstrcpy(new_name, p+1);
1604 fstrcpy(driver->helpfile, new_name);
1607 if (driver->dependentfiles) {
1608 for (i=0; *driver->dependentfiles[i]; i++) {
1609 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1610 fstrcpy(new_name, p+1);
1611 fstrcpy(driver->dependentfiles[i], new_name);
1616 architecture = get_short_archi(driver->environment);
1618 /* jfm:7/16/2000 the client always sends the cversion=0.
1619 * The server should check which version the driver is by reading
1620 * the PE header of driver->driverpath.
1622 * For Windows 95/98 the version is 0 (so the value sent is correct)
1623 * For Windows NT (the architecture doesn't matter)
1624 * NT 3.1: cversion=0
1625 * NT 3.5/3.51: cversion=1
1626 * NT 4: cversion=2
1627 * NT2K: cversion=3
1630 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1631 return err;
1633 return WERR_OK;
1636 /****************************************************************************
1637 ****************************************************************************/
1638 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1639 uint32 level, struct current_user *user)
1641 switch (level) {
1642 case 3:
1644 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1645 driver=driver_abstract.info_3;
1646 return clean_up_driver_struct_level_3(driver, user);
1648 case 6:
1650 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1651 driver=driver_abstract.info_6;
1652 return clean_up_driver_struct_level_6(driver, user);
1654 default:
1655 return WERR_INVALID_PARAM;
1659 /****************************************************************************
1660 This function sucks and should be replaced. JRA.
1661 ****************************************************************************/
1663 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1665 dst->cversion = src->version;
1667 fstrcpy( dst->name, src->name);
1668 fstrcpy( dst->environment, src->environment);
1669 fstrcpy( dst->driverpath, src->driverpath);
1670 fstrcpy( dst->datafile, src->datafile);
1671 fstrcpy( dst->configfile, src->configfile);
1672 fstrcpy( dst->helpfile, src->helpfile);
1673 fstrcpy( dst->monitorname, src->monitorname);
1674 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1675 dst->dependentfiles = src->dependentfiles;
1678 #if 0 /* Debugging function */
1680 static char* ffmt(unsigned char *c){
1681 int i;
1682 static char ffmt_str[17];
1684 for (i=0; i<16; i++) {
1685 if ((c[i] < ' ') || (c[i] > '~'))
1686 ffmt_str[i]='.';
1687 else
1688 ffmt_str[i]=c[i];
1690 ffmt_str[16]='\0';
1691 return ffmt_str;
1694 #endif
1696 /****************************************************************************
1697 ****************************************************************************/
1698 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1699 struct current_user *user, WERROR *perr)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1702 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1703 const char *architecture;
1704 pstring new_dir;
1705 pstring old_name;
1706 pstring new_name;
1707 DATA_BLOB null_pw;
1708 connection_struct *conn;
1709 NTSTATUS nt_status;
1710 pstring inbuf;
1711 pstring outbuf;
1712 fstring res_type;
1713 BOOL bad_path;
1714 SMB_STRUCT_STAT st;
1715 int ver = 0;
1716 int i;
1717 int err;
1719 memset(inbuf, '\0', sizeof(inbuf));
1720 memset(outbuf, '\0', sizeof(outbuf));
1721 *perr = WERR_OK;
1723 if (level==3)
1724 driver=driver_abstract.info_3;
1725 else if (level==6) {
1726 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1727 driver = &converted_driver;
1728 } else {
1729 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1730 return WERR_UNKNOWN_LEVEL;
1733 architecture = get_short_archi(driver->environment);
1736 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1737 * Note we must be root to do this.
1740 null_pw = data_blob(NULL, 0);
1741 fstrcpy(res_type, "A:");
1742 become_root();
1743 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1744 unbecome_root();
1746 if (conn == NULL) {
1747 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1748 *perr = ntstatus_to_werror(nt_status);
1749 return WERR_NO_SUCH_SHARE;
1753 * Save who we are - we are temporarily becoming the connection user.
1756 if (!become_user(conn, conn->vuid)) {
1757 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1758 return WERR_ACCESS_DENIED;
1762 * make the directories version and version\driver_name
1763 * under the architecture directory.
1765 DEBUG(5,("Creating first directory\n"));
1766 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1767 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1768 mkdir_internal(conn, new_dir, bad_path);
1770 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1771 * listed for this driver which has already been moved, skip it (note:
1772 * drivers may list the same file name several times. Then check if the
1773 * file already exists in archi\cversion\, if so, check that the version
1774 * info (or time stamps if version info is unavailable) is newer (or the
1775 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1776 * Otherwise, delete the file.
1778 * If a file is not moved to archi\cversion\ because of an error, all the
1779 * rest of the 'unmoved' driver files are removed from archi\. If one or
1780 * more of the driver's files was already moved to archi\cversion\, it
1781 * potentially leaves the driver in a partially updated state. Version
1782 * trauma will most likely occur if an client attempts to use any printer
1783 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1784 * done is appropriate... later JRR
1787 DEBUG(5,("Moving files now !\n"));
1789 if (driver->driverpath && strlen(driver->driverpath)) {
1790 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1791 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1792 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1793 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1794 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1795 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1796 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1797 new_name, old_name));
1798 *perr = WERR_ACCESS_DENIED;
1799 ver = -1;
1804 if (driver->datafile && strlen(driver->datafile)) {
1805 if (!strequal(driver->datafile, driver->driverpath)) {
1806 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1807 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1808 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1809 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1810 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1811 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1812 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1813 new_name, old_name));
1814 *perr = WERR_ACCESS_DENIED;
1815 ver = -1;
1821 if (driver->configfile && strlen(driver->configfile)) {
1822 if (!strequal(driver->configfile, driver->driverpath) &&
1823 !strequal(driver->configfile, driver->datafile)) {
1824 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1825 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1826 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1827 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1828 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1829 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1830 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1831 new_name, old_name));
1832 *perr = WERR_ACCESS_DENIED;
1833 ver = -1;
1839 if (driver->helpfile && strlen(driver->helpfile)) {
1840 if (!strequal(driver->helpfile, driver->driverpath) &&
1841 !strequal(driver->helpfile, driver->datafile) &&
1842 !strequal(driver->helpfile, driver->configfile)) {
1843 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1844 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1845 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1846 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1847 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1848 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1849 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1850 new_name, old_name));
1851 *perr = WERR_ACCESS_DENIED;
1852 ver = -1;
1858 if (driver->dependentfiles) {
1859 for (i=0; *driver->dependentfiles[i]; i++) {
1860 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1861 !strequal(driver->dependentfiles[i], driver->datafile) &&
1862 !strequal(driver->dependentfiles[i], driver->configfile) &&
1863 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1864 int j;
1865 for (j=0; j < i; j++) {
1866 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1867 goto NextDriver;
1871 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1872 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1873 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1874 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1875 if ( !copy_file(new_name, old_name, conn,
1876 OPENX_FILE_EXISTS_TRUNCATE|
1877 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1878 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1879 new_name, old_name));
1880 *perr = WERR_ACCESS_DENIED;
1881 ver = -1;
1885 NextDriver: ;
1889 close_cnum(conn, user->vuid);
1890 unbecome_user();
1892 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1895 /****************************************************************************
1896 ****************************************************************************/
1897 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1899 int len, buflen;
1900 const char *architecture;
1901 pstring directory;
1902 fstring temp_name;
1903 pstring key;
1904 char *buf;
1905 int i, ret;
1906 TDB_DATA kbuf, dbuf;
1908 architecture = get_short_archi(driver->environment);
1910 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1911 * \\server is added in the rpc server layer.
1912 * It does make sense to NOT store the server's name in the printer TDB.
1915 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1917 /* .inf files do not always list a file for each of the four standard files.
1918 * Don't prepend a path to a null filename, or client claims:
1919 * "The server on which the printer resides does not have a suitable
1920 * <printer driver name> printer driver installed. Click OK if you
1921 * wish to install the driver on your local machine."
1923 if (strlen(driver->driverpath)) {
1924 fstrcpy(temp_name, driver->driverpath);
1925 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1928 if (strlen(driver->datafile)) {
1929 fstrcpy(temp_name, driver->datafile);
1930 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1933 if (strlen(driver->configfile)) {
1934 fstrcpy(temp_name, driver->configfile);
1935 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1938 if (strlen(driver->helpfile)) {
1939 fstrcpy(temp_name, driver->helpfile);
1940 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1943 if (driver->dependentfiles) {
1944 for (i=0; *driver->dependentfiles[i]; i++) {
1945 fstrcpy(temp_name, driver->dependentfiles[i]);
1946 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1950 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1952 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1954 buf = NULL;
1955 len = buflen = 0;
1957 again:
1958 len = 0;
1959 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1960 driver->cversion,
1961 driver->name,
1962 driver->environment,
1963 driver->driverpath,
1964 driver->datafile,
1965 driver->configfile,
1966 driver->helpfile,
1967 driver->monitorname,
1968 driver->defaultdatatype);
1970 if (driver->dependentfiles) {
1971 for (i=0; *driver->dependentfiles[i]; i++) {
1972 len += tdb_pack(buf+len, buflen-len, "f",
1973 driver->dependentfiles[i]);
1977 if (len != buflen) {
1978 char *tb;
1980 tb = (char *)SMB_REALLOC(buf, len);
1981 if (!tb) {
1982 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1983 ret = -1;
1984 goto done;
1986 else buf = tb;
1987 buflen = len;
1988 goto again;
1992 kbuf.dptr = key;
1993 kbuf.dsize = strlen(key)+1;
1994 dbuf.dptr = buf;
1995 dbuf.dsize = len;
1997 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1999 done:
2000 if (ret)
2001 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2003 SAFE_FREE(buf);
2004 return ret;
2007 /****************************************************************************
2008 ****************************************************************************/
2009 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2011 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2013 ZERO_STRUCT(info3);
2014 info3.cversion = driver->version;
2015 fstrcpy(info3.name,driver->name);
2016 fstrcpy(info3.environment,driver->environment);
2017 fstrcpy(info3.driverpath,driver->driverpath);
2018 fstrcpy(info3.datafile,driver->datafile);
2019 fstrcpy(info3.configfile,driver->configfile);
2020 fstrcpy(info3.helpfile,driver->helpfile);
2021 fstrcpy(info3.monitorname,driver->monitorname);
2022 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2023 info3.dependentfiles = driver->dependentfiles;
2025 return add_a_printer_driver_3(&info3);
2029 /****************************************************************************
2030 ****************************************************************************/
2031 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2033 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2035 ZERO_STRUCT(info);
2037 fstrcpy(info.name, driver);
2038 fstrcpy(info.defaultdatatype, "RAW");
2040 fstrcpy(info.driverpath, "");
2041 fstrcpy(info.datafile, "");
2042 fstrcpy(info.configfile, "");
2043 fstrcpy(info.helpfile, "");
2045 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2046 return WERR_NOMEM;
2048 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2049 fstrcpy(info.dependentfiles[0], "");
2051 *info_ptr = memdup(&info, sizeof(info));
2053 return WERR_OK;
2056 /****************************************************************************
2057 ****************************************************************************/
2058 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2060 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2061 TDB_DATA kbuf, dbuf;
2062 const char *architecture;
2063 int len = 0;
2064 int i;
2065 pstring key;
2067 ZERO_STRUCT(driver);
2069 architecture = get_short_archi(arch);
2071 if ( !architecture )
2072 return WERR_UNKNOWN_PRINTER_DRIVER;
2074 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2076 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2077 version = 0;
2079 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2081 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2083 kbuf.dptr = key;
2084 kbuf.dsize = strlen(key)+1;
2086 dbuf = tdb_fetch(tdb_drivers, kbuf);
2087 if (!dbuf.dptr)
2088 return WERR_UNKNOWN_PRINTER_DRIVER;
2090 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2091 &driver.cversion,
2092 driver.name,
2093 driver.environment,
2094 driver.driverpath,
2095 driver.datafile,
2096 driver.configfile,
2097 driver.helpfile,
2098 driver.monitorname,
2099 driver.defaultdatatype);
2101 i=0;
2102 while (len < dbuf.dsize) {
2103 fstring *tddfs;
2105 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2106 if ( !tddfs ) {
2107 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2108 break;
2110 else
2111 driver.dependentfiles = tddfs;
2113 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2114 &driver.dependentfiles[i]);
2115 i++;
2118 if ( driver.dependentfiles )
2119 fstrcpy( driver.dependentfiles[i], "" );
2121 SAFE_FREE(dbuf.dptr);
2123 if (len != dbuf.dsize) {
2124 SAFE_FREE(driver.dependentfiles);
2126 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2129 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2131 return WERR_OK;
2134 /****************************************************************************
2135 Debugging function, dump at level 6 the struct in the logs.
2136 ****************************************************************************/
2138 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2140 uint32 result;
2141 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2142 int i;
2144 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2146 switch (level)
2148 case 3:
2150 if (driver.info_3 == NULL)
2151 result=5;
2152 else {
2153 info3=driver.info_3;
2155 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2156 DEBUGADD(20,("name:[%s]\n", info3->name));
2157 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2158 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2159 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2160 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2161 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2162 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2163 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2165 for (i=0; info3->dependentfiles &&
2166 *info3->dependentfiles[i]; i++) {
2167 DEBUGADD(20,("dependentfile:[%s]\n",
2168 info3->dependentfiles[i]));
2170 result=0;
2172 break;
2174 default:
2175 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2176 result=1;
2177 break;
2180 return result;
2183 /****************************************************************************
2184 ****************************************************************************/
2185 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2187 int len = 0;
2189 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2191 if (!nt_devmode)
2192 return len;
2194 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2195 nt_devmode->devicename,
2196 nt_devmode->formname,
2198 nt_devmode->specversion,
2199 nt_devmode->driverversion,
2200 nt_devmode->size,
2201 nt_devmode->driverextra,
2202 nt_devmode->orientation,
2203 nt_devmode->papersize,
2204 nt_devmode->paperlength,
2205 nt_devmode->paperwidth,
2206 nt_devmode->scale,
2207 nt_devmode->copies,
2208 nt_devmode->defaultsource,
2209 nt_devmode->printquality,
2210 nt_devmode->color,
2211 nt_devmode->duplex,
2212 nt_devmode->yresolution,
2213 nt_devmode->ttoption,
2214 nt_devmode->collate,
2215 nt_devmode->logpixels,
2217 nt_devmode->fields,
2218 nt_devmode->bitsperpel,
2219 nt_devmode->pelswidth,
2220 nt_devmode->pelsheight,
2221 nt_devmode->displayflags,
2222 nt_devmode->displayfrequency,
2223 nt_devmode->icmmethod,
2224 nt_devmode->icmintent,
2225 nt_devmode->mediatype,
2226 nt_devmode->dithertype,
2227 nt_devmode->reserved1,
2228 nt_devmode->reserved2,
2229 nt_devmode->panningwidth,
2230 nt_devmode->panningheight,
2231 nt_devmode->nt_dev_private);
2234 if (nt_devmode->nt_dev_private) {
2235 len += tdb_pack(buf+len, buflen-len, "B",
2236 nt_devmode->driverextra,
2237 nt_devmode->nt_dev_private);
2240 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2242 return len;
2245 /****************************************************************************
2246 Pack all values in all printer keys
2247 ***************************************************************************/
2249 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2251 int len = 0;
2252 int i, j;
2253 REGISTRY_VALUE *val;
2254 REGVAL_CTR *val_ctr;
2255 pstring path;
2256 int num_values;
2258 if ( !data )
2259 return 0;
2261 /* loop over all keys */
2263 for ( i=0; i<data->num_keys; i++ ) {
2264 val_ctr = &data->keys[i].values;
2265 num_values = regval_ctr_numvals( val_ctr );
2267 /* pack the keyname followed by a empty value */
2269 len += tdb_pack(buf+len, buflen-len, "pPdB",
2270 &data->keys[i].name,
2271 data->keys[i].name,
2272 REG_NONE,
2274 NULL);
2276 /* now loop over all values */
2278 for ( j=0; j<num_values; j++ ) {
2279 /* pathname should be stored as <key>\<value> */
2281 val = regval_ctr_specific_value( val_ctr, j );
2282 pstrcpy( path, data->keys[i].name );
2283 pstrcat( path, "\\" );
2284 pstrcat( path, regval_name(val) );
2286 len += tdb_pack(buf+len, buflen-len, "pPdB",
2287 val,
2288 path,
2289 regval_type(val),
2290 regval_size(val),
2291 regval_data_p(val) );
2296 /* terminator */
2298 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2300 return len;
2304 /****************************************************************************
2305 Delete a printer - this just deletes the printer info file, any open
2306 handles are not affected.
2307 ****************************************************************************/
2309 uint32 del_a_printer(const char *sharename)
2311 pstring key;
2312 TDB_DATA kbuf;
2313 pstring printdb_path;
2315 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2316 kbuf.dptr=key;
2317 kbuf.dsize=strlen(key)+1;
2318 tdb_delete(tdb_printers, kbuf);
2320 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2321 kbuf.dptr=key;
2322 kbuf.dsize=strlen(key)+1;
2323 tdb_delete(tdb_printers, kbuf);
2325 close_all_print_db();
2327 if (geteuid() == 0) {
2328 pstrcpy(printdb_path, lock_path("printing/"));
2329 pstrcat(printdb_path, sharename);
2330 pstrcat(printdb_path, ".tdb");
2332 unlink(printdb_path);
2335 return 0;
2338 /****************************************************************************
2339 ****************************************************************************/
2340 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2342 char *buf;
2343 int buflen, len;
2344 WERROR ret;
2345 TDB_DATA kbuf, dbuf;
2348 * in addprinter: no servername and the printer is the name
2349 * in setprinter: servername is \\server
2350 * and printer is \\server\\printer
2352 * Samba manages only local printers.
2353 * we currently don't support things like i
2354 * path=\\other_server\printer
2356 * We only store the printername, not \\server\printername
2359 if ( info->servername[0] != '\0' ) {
2360 trim_string(info->printername, info->servername, NULL);
2361 trim_char(info->printername, '\\', '\0');
2362 info->servername[0]='\0';
2366 * JFM: one day I'll forget.
2367 * below that's info->portname because that's the SAMBA sharename
2368 * and I made NT 'thinks' it's the portname
2369 * the info->sharename is the thing you can name when you add a printer
2370 * that's the short-name when you create shared printer for 95/98
2371 * So I've made a limitation in SAMBA: you can only have 1 printer model
2372 * behind a SAMBA share.
2375 buf = NULL;
2376 buflen = 0;
2378 again:
2379 len = 0;
2380 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2381 info->attributes,
2382 info->priority,
2383 info->default_priority,
2384 info->starttime,
2385 info->untiltime,
2386 info->status,
2387 info->cjobs,
2388 info->averageppm,
2389 info->changeid,
2390 info->c_setprinter,
2391 info->setuptime,
2392 info->servername,
2393 info->printername,
2394 info->sharename,
2395 info->portname,
2396 info->drivername,
2397 info->comment,
2398 info->location,
2399 info->sepfile,
2400 info->printprocessor,
2401 info->datatype,
2402 info->parameters);
2404 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2406 len += pack_values( &info->data, buf+len, buflen-len );
2408 if (buflen != len) {
2409 char *tb;
2411 tb = (char *)SMB_REALLOC(buf, len);
2412 if (!tb) {
2413 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2414 ret = WERR_NOMEM;
2415 goto done;
2417 else buf = tb;
2418 buflen = len;
2419 goto again;
2423 kbuf = make_printer_tdbkey( info->sharename );
2425 dbuf.dptr = buf;
2426 dbuf.dsize = len;
2428 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2430 done:
2431 if (!W_ERROR_IS_OK(ret))
2432 DEBUG(8, ("error updating printer to tdb on disk\n"));
2434 SAFE_FREE(buf);
2436 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2437 info->sharename, info->drivername, info->portname, len));
2439 return ret;
2443 /****************************************************************************
2444 Malloc and return an NT devicemode.
2445 ****************************************************************************/
2447 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2450 char adevice[MAXDEVICENAME];
2451 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2453 if (nt_devmode == NULL) {
2454 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2455 return NULL;
2458 ZERO_STRUCTP(nt_devmode);
2460 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2461 fstrcpy(nt_devmode->devicename, adevice);
2463 fstrcpy(nt_devmode->formname, "Letter");
2465 nt_devmode->specversion = 0x0401;
2466 nt_devmode->driverversion = 0x0400;
2467 nt_devmode->size = 0x00DC;
2468 nt_devmode->driverextra = 0x0000;
2469 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2470 DEFAULTSOURCE | COPIES | SCALE |
2471 PAPERSIZE | ORIENTATION;
2472 nt_devmode->orientation = 1;
2473 nt_devmode->papersize = PAPER_LETTER;
2474 nt_devmode->paperlength = 0;
2475 nt_devmode->paperwidth = 0;
2476 nt_devmode->scale = 0x64;
2477 nt_devmode->copies = 1;
2478 nt_devmode->defaultsource = BIN_FORMSOURCE;
2479 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2480 nt_devmode->color = COLOR_MONOCHROME;
2481 nt_devmode->duplex = DUP_SIMPLEX;
2482 nt_devmode->yresolution = 0;
2483 nt_devmode->ttoption = TT_SUBDEV;
2484 nt_devmode->collate = COLLATE_FALSE;
2485 nt_devmode->icmmethod = 0;
2486 nt_devmode->icmintent = 0;
2487 nt_devmode->mediatype = 0;
2488 nt_devmode->dithertype = 0;
2490 /* non utilisés par un driver d'imprimante */
2491 nt_devmode->logpixels = 0;
2492 nt_devmode->bitsperpel = 0;
2493 nt_devmode->pelswidth = 0;
2494 nt_devmode->pelsheight = 0;
2495 nt_devmode->displayflags = 0;
2496 nt_devmode->displayfrequency = 0;
2497 nt_devmode->reserved1 = 0;
2498 nt_devmode->reserved2 = 0;
2499 nt_devmode->panningwidth = 0;
2500 nt_devmode->panningheight = 0;
2502 nt_devmode->nt_dev_private = NULL;
2503 return nt_devmode;
2506 /****************************************************************************
2507 Deepcopy an NT devicemode.
2508 ****************************************************************************/
2510 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2512 NT_DEVICEMODE *new_nt_devicemode = NULL;
2514 if ( !nt_devicemode )
2515 return NULL;
2517 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2518 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2519 return NULL;
2522 new_nt_devicemode->nt_dev_private = NULL;
2523 if (nt_devicemode->nt_dev_private != NULL) {
2524 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2525 SAFE_FREE(new_nt_devicemode);
2526 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2527 return NULL;
2531 return new_nt_devicemode;
2534 /****************************************************************************
2535 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2536 ****************************************************************************/
2538 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2540 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2542 if(nt_devmode == NULL)
2543 return;
2545 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2547 SAFE_FREE(nt_devmode->nt_dev_private);
2548 SAFE_FREE(*devmode_ptr);
2551 /****************************************************************************
2552 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2553 ****************************************************************************/
2554 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2556 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2557 NT_PRINTER_DATA *data;
2558 int i;
2560 if ( !info )
2561 return;
2563 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2565 free_nt_devicemode(&info->devmode);
2567 /* clean up all registry keys */
2569 data = &info->data;
2570 for ( i=0; i<data->num_keys; i++ ) {
2571 SAFE_FREE( data->keys[i].name );
2572 regval_ctr_destroy( &data->keys[i].values );
2574 SAFE_FREE( data->keys );
2576 /* finally the top level structure */
2578 SAFE_FREE( *info_ptr );
2582 /****************************************************************************
2583 ****************************************************************************/
2584 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2586 int len = 0;
2587 int extra_len = 0;
2588 NT_DEVICEMODE devmode;
2590 ZERO_STRUCT(devmode);
2592 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2594 if (!*nt_devmode) return len;
2596 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2597 devmode.devicename,
2598 devmode.formname,
2600 &devmode.specversion,
2601 &devmode.driverversion,
2602 &devmode.size,
2603 &devmode.driverextra,
2604 &devmode.orientation,
2605 &devmode.papersize,
2606 &devmode.paperlength,
2607 &devmode.paperwidth,
2608 &devmode.scale,
2609 &devmode.copies,
2610 &devmode.defaultsource,
2611 &devmode.printquality,
2612 &devmode.color,
2613 &devmode.duplex,
2614 &devmode.yresolution,
2615 &devmode.ttoption,
2616 &devmode.collate,
2617 &devmode.logpixels,
2619 &devmode.fields,
2620 &devmode.bitsperpel,
2621 &devmode.pelswidth,
2622 &devmode.pelsheight,
2623 &devmode.displayflags,
2624 &devmode.displayfrequency,
2625 &devmode.icmmethod,
2626 &devmode.icmintent,
2627 &devmode.mediatype,
2628 &devmode.dithertype,
2629 &devmode.reserved1,
2630 &devmode.reserved2,
2631 &devmode.panningwidth,
2632 &devmode.panningheight,
2633 &devmode.nt_dev_private);
2635 if (devmode.nt_dev_private) {
2636 /* the len in tdb_unpack is an int value and
2637 * devmode.driverextra is only a short
2639 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2640 devmode.driverextra=(uint16)extra_len;
2642 /* check to catch an invalid TDB entry so we don't segfault */
2643 if (devmode.driverextra == 0) {
2644 devmode.nt_dev_private = NULL;
2648 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2650 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2651 if (devmode.nt_dev_private)
2652 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2654 return len;
2657 /****************************************************************************
2658 Allocate and initialize a new slot.
2659 ***************************************************************************/
2661 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2663 NT_PRINTER_KEY *d;
2664 int key_index;
2666 if ( !data || !name )
2667 return -1;
2669 /* allocate another slot in the NT_PRINTER_KEY array */
2671 if ( !(d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2672 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2673 return -1;
2676 data->keys = d;
2678 key_index = data->num_keys;
2680 /* initialze new key */
2682 data->num_keys++;
2683 data->keys[key_index].name = SMB_STRDUP( name );
2685 regval_ctr_init( &data->keys[key_index].values );
2687 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2689 return key_index;
2692 /****************************************************************************
2693 search for a registry key name in the existing printer data
2694 ***************************************************************************/
2696 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2698 int i;
2699 NT_PRINTER_KEY *printer_key;
2701 for ( i=0; i<data->num_keys; i++ ) {
2702 if ( strequal( data->keys[i].name, name ) ) {
2704 /* cleanup memory */
2706 printer_key = &data->keys[i];
2707 SAFE_FREE( printer_key->name );
2708 regval_ctr_destroy( &printer_key->values );
2710 /* if not the end of the array, move remaining elements down one slot */
2712 data->num_keys--;
2713 if ( data->num_keys && (i < data->num_keys) )
2714 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2716 break;
2721 return data->num_keys;
2724 /****************************************************************************
2725 search for a registry key name in the existing printer data
2726 ***************************************************************************/
2728 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2730 int key_index = -1;
2731 int i;
2733 if ( !data || !name )
2734 return -1;
2736 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2738 /* loop over all existing keys */
2740 for ( i=0; i<data->num_keys; i++ ) {
2741 if ( strequal(data->keys[i].name, name) ) {
2742 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2743 key_index = i;
2744 break;
2749 return key_index;
2752 /****************************************************************************
2753 ***************************************************************************/
2755 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2757 int i, j;
2758 int key_len;
2759 int num_subkeys = 0;
2760 char *p;
2761 fstring *ptr, *subkeys_ptr = NULL;
2762 fstring subkeyname;
2764 if ( !data )
2765 return 0;
2767 if ( !key )
2768 return -1;
2770 /* special case of asking for the top level printer data registry key names */
2772 if ( strlen(key) == 0 ) {
2773 for ( i=0; i<data->num_keys; i++ ) {
2775 /* found a match, so allocate space and copy the name */
2777 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2778 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2779 num_subkeys+1));
2780 SAFE_FREE( subkeys );
2781 return -1;
2784 subkeys_ptr = ptr;
2785 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2786 num_subkeys++;
2789 goto done;
2792 /* asking for the subkeys of some key */
2793 /* subkey paths are stored in the key name using '\' as the delimiter */
2795 for ( i=0; i<data->num_keys; i++ ) {
2796 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2798 /* if we found the exact key, then break */
2799 key_len = strlen( key );
2800 if ( strlen(data->keys[i].name) == key_len )
2801 break;
2803 /* get subkey path */
2805 p = data->keys[i].name + key_len;
2806 if ( *p == '\\' )
2807 p++;
2808 fstrcpy( subkeyname, p );
2809 if ( (p = strchr( subkeyname, '\\' )) )
2810 *p = '\0';
2812 /* don't add a key more than once */
2814 for ( j=0; j<num_subkeys; j++ ) {
2815 if ( strequal( subkeys_ptr[j], subkeyname ) )
2816 break;
2819 if ( j != num_subkeys )
2820 continue;
2822 /* found a match, so allocate space and copy the name */
2824 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2825 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2826 num_subkeys+1));
2827 SAFE_FREE( subkeys );
2828 return 0;
2831 subkeys_ptr = ptr;
2832 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2833 num_subkeys++;
2838 /* return error if the key was not found */
2840 if ( i == data->num_keys )
2841 return -1;
2843 done:
2844 /* tag off the end */
2846 if (num_subkeys)
2847 fstrcpy(subkeys_ptr[num_subkeys], "" );
2849 *subkeys = subkeys_ptr;
2851 return num_subkeys;
2854 #ifdef HAVE_ADS
2855 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2856 const char *sz)
2858 smb_ucs2_t conv_str[1024];
2859 size_t str_size;
2861 regval_ctr_delvalue(ctr, val_name);
2862 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2863 STR_TERMINATE | STR_NOALIGN);
2864 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2865 (char *) conv_str, str_size);
2868 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2869 uint32 dword)
2871 regval_ctr_delvalue(ctr, val_name);
2872 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2873 (char *) &dword, sizeof(dword));
2876 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2877 BOOL b)
2879 uint8 bin_bool = (b ? 1 : 0);
2880 regval_ctr_delvalue(ctr, val_name);
2881 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2882 (char *) &bin_bool, sizeof(bin_bool));
2885 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2886 const char *multi_sz)
2888 smb_ucs2_t *conv_strs = NULL;
2889 size_t str_size;
2891 /* a multi-sz has to have a null string terminator, i.e., the last
2892 string must be followed by two nulls */
2893 str_size = strlen(multi_sz) + 2;
2894 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2895 if (!conv_strs) {
2896 return;
2899 /* Change to byte units. */
2900 str_size *= sizeof(smb_ucs2_t);
2901 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2902 STR_TERMINATE | STR_NOALIGN);
2904 regval_ctr_delvalue(ctr, val_name);
2905 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2906 (char *) conv_strs, str_size);
2907 safe_free(conv_strs);
2911 /****************************************************************************
2912 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2914 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2915 * @return BOOL indicating success or failure
2916 ***************************************************************************/
2918 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2920 REGVAL_CTR *ctr = NULL;
2921 fstring longname;
2922 fstring dnssuffix;
2923 char *allocated_string = NULL;
2924 const char *ascii_str;
2925 int i;
2927 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2928 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2929 ctr = &info2->data.keys[i].values;
2931 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2932 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2934 /* we make the assumption that the netbios name is the same
2935 as the DNS name sinc ethe former will be what we used to
2936 join the domain */
2938 if ( get_mydnsdomname( dnssuffix ) )
2939 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2940 else
2941 fstrcpy( longname, global_myname() );
2943 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2945 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2946 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2947 SAFE_FREE(allocated_string);
2949 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2950 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2951 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2952 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2953 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2954 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2955 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2956 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2957 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2959 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2960 (info2->attributes &
2961 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2963 switch (info2->attributes & 0x3) {
2964 case 0:
2965 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2966 break;
2967 case 1:
2968 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2969 break;
2970 case 2:
2971 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2972 break;
2973 default:
2974 ascii_str = "unknown";
2976 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2978 return True;
2981 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2982 struct uuid guid)
2984 int i;
2985 REGVAL_CTR *ctr=NULL;
2987 /* find the DsSpooler key */
2988 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2989 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2990 ctr = &info2->data.keys[i].values;
2992 regval_ctr_delvalue(ctr, "objectGUID");
2993 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2994 (char *) &guid, sizeof(struct uuid));
2997 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2998 NT_PRINTER_INFO_LEVEL *printer)
3000 ADS_STATUS ads_rc;
3001 void *res;
3002 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
3003 char *srv_dn_utf8, **srv_cn_utf8;
3004 TALLOC_CTX *ctx;
3005 ADS_MODLIST mods;
3006 const char *attrs[] = {"objectGUID", NULL};
3007 struct uuid guid;
3008 WERROR win_rc = WERR_OK;
3010 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3012 /* figure out where to publish */
3013 ads_find_machine_acct(ads, &res, global_myname());
3015 /* We use ldap_get_dn here as we need the answer
3016 * in utf8 to call ldap_explode_dn(). JRA. */
3018 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
3019 if (!srv_dn_utf8) {
3020 ads_destroy(&ads);
3021 return WERR_SERVER_UNAVAILABLE;
3023 ads_msgfree(ads, res);
3024 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3025 if (!srv_cn_utf8) {
3026 ldap_memfree(srv_dn_utf8);
3027 ads_destroy(&ads);
3028 return WERR_SERVER_UNAVAILABLE;
3030 /* Now convert to CH_UNIX. */
3031 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3032 ldap_memfree(srv_dn_utf8);
3033 ldap_memfree(srv_cn_utf8);
3034 ads_destroy(&ads);
3035 return WERR_SERVER_UNAVAILABLE;
3037 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3038 ldap_memfree(srv_dn_utf8);
3039 ldap_memfree(srv_cn_utf8);
3040 ads_destroy(&ads);
3041 SAFE_FREE(srv_dn);
3042 return WERR_SERVER_UNAVAILABLE;
3045 ldap_memfree(srv_dn_utf8);
3046 ldap_memfree(srv_cn_utf8);
3048 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
3049 printer->info_2->sharename, srv_dn);
3051 SAFE_FREE(srv_dn);
3052 SAFE_FREE(srv_cn_0);
3054 /* build the ads mods */
3055 ctx = talloc_init("nt_printer_publish_ads");
3056 mods = ads_init_mods(ctx);
3058 get_local_printer_publishing_data(ctx, &mods,
3059 &printer->info_2->data);
3060 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3061 printer->info_2->sharename);
3063 /* publish it */
3064 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3065 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3066 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3068 if (!ADS_ERR_OK(ads_rc))
3069 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3071 talloc_destroy(ctx);
3073 /* retreive the guid and store it locally */
3074 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3075 ZERO_STRUCT(guid);
3076 ads_pull_guid(ads, res, &guid);
3077 ads_msgfree(ads, res);
3078 store_printer_guid(printer->info_2, guid);
3079 win_rc = mod_a_printer(printer, 2);
3082 SAFE_FREE(prt_dn);
3083 return win_rc;
3086 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3087 NT_PRINTER_INFO_LEVEL *printer)
3089 ADS_STATUS ads_rc;
3090 void *res;
3091 char *prt_dn = NULL;
3093 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3095 /* remove the printer from the directory */
3096 ads_rc = ads_find_printer_on_server(ads, &res,
3097 printer->info_2->sharename, global_myname());
3099 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3100 prt_dn = ads_get_dn(ads, res);
3101 ads_rc = ads_del_dn(ads, prt_dn);
3102 ads_memfree(ads, prt_dn);
3105 ads_msgfree(ads, res);
3106 return WERR_OK;
3109 /****************************************************************************
3110 * Publish a printer in the directory
3112 * @param snum describing printer service
3113 * @return WERROR indicating status of publishing
3114 ***************************************************************************/
3116 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3118 ADS_STATUS ads_rc;
3119 ADS_STRUCT *ads = NULL;
3120 NT_PRINTER_INFO_LEVEL *printer = NULL;
3121 WERROR win_rc;
3123 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3124 if (!W_ERROR_IS_OK(win_rc))
3125 goto done;
3127 switch (action) {
3128 case SPOOL_DS_PUBLISH:
3129 case SPOOL_DS_UPDATE:
3130 /* set the DsSpooler info and attributes */
3131 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3132 win_rc = WERR_NOMEM;
3133 goto done;
3136 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3137 break;
3138 case SPOOL_DS_UNPUBLISH:
3139 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3140 break;
3141 default:
3142 win_rc = WERR_NOT_SUPPORTED;
3143 goto done;
3146 win_rc = mod_a_printer(printer, 2);
3147 if (!W_ERROR_IS_OK(win_rc)) {
3148 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3149 goto done;
3152 ads = ads_init(NULL, NULL, NULL);
3153 if (!ads) {
3154 DEBUG(3, ("ads_init() failed\n"));
3155 win_rc = WERR_SERVER_UNAVAILABLE;
3156 goto done;
3158 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3159 SAFE_FREE(ads->auth.password);
3160 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3161 NULL, NULL);
3163 /* ads_connect() will find the DC for us */
3164 ads_rc = ads_connect(ads);
3165 if (!ADS_ERR_OK(ads_rc)) {
3166 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3167 win_rc = WERR_ACCESS_DENIED;
3168 goto done;
3171 switch (action) {
3172 case SPOOL_DS_PUBLISH:
3173 case SPOOL_DS_UPDATE:
3174 win_rc = nt_printer_publish_ads(ads, printer);
3175 break;
3176 case SPOOL_DS_UNPUBLISH:
3177 win_rc = nt_printer_unpublish_ads(ads, printer);
3178 break;
3181 done:
3182 free_a_printer(&printer, 2);
3183 ads_destroy(&ads);
3184 return win_rc;
3187 WERROR check_published_printers(void)
3189 ADS_STATUS ads_rc;
3190 ADS_STRUCT *ads = NULL;
3191 int snum;
3192 int n_services = lp_numservices();
3193 NT_PRINTER_INFO_LEVEL *printer = NULL;
3195 ads = ads_init(NULL, NULL, NULL);
3196 if (!ads) {
3197 DEBUG(3, ("ads_init() failed\n"));
3198 return WERR_SERVER_UNAVAILABLE;
3200 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3201 SAFE_FREE(ads->auth.password);
3202 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3203 NULL, NULL);
3205 /* ads_connect() will find the DC for us */
3206 ads_rc = ads_connect(ads);
3207 if (!ADS_ERR_OK(ads_rc)) {
3208 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3209 ads_destroy(&ads);
3210 return WERR_ACCESS_DENIED;
3213 for (snum = 0; snum < n_services; snum++) {
3214 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3215 continue;
3217 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3218 lp_servicename(snum))) &&
3219 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3220 nt_printer_publish_ads(ads, printer);
3222 free_a_printer(&printer, 2);
3225 ads_destroy(&ads);
3226 return WERR_OK;
3229 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3230 struct uuid *guid)
3232 NT_PRINTER_INFO_LEVEL *printer = NULL;
3233 REGVAL_CTR *ctr;
3234 REGISTRY_VALUE *guid_val;
3235 WERROR win_rc;
3236 int i;
3238 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3240 if (!W_ERROR_IS_OK(win_rc) ||
3241 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3242 ((i = lookup_printerkey(&printer->info_2->data,
3243 SPOOL_DSSPOOLER_KEY)) < 0) ||
3244 !(ctr = &printer->info_2->data.keys[i].values) ||
3245 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3246 free_a_printer(&printer, 2);
3247 return False;
3250 /* fetching printer guids really ought to be a separate function.. */
3251 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3252 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3254 free_a_printer(&printer, 2);
3255 return True;
3257 #else
3258 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3260 return WERR_OK;
3263 WERROR check_published_printers(void)
3265 return WERR_OK;
3268 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3269 struct uuid *guid)
3271 return False;
3273 #endif /* HAVE_ADS */
3275 /****************************************************************************
3276 ***************************************************************************/
3278 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3280 NT_PRINTER_DATA *data;
3281 int i;
3282 int removed_keys = 0;
3283 int empty_slot;
3285 data = &p2->data;
3286 empty_slot = data->num_keys;
3288 if ( !key )
3289 return WERR_INVALID_PARAM;
3291 /* remove all keys */
3293 if ( !strlen(key) ) {
3294 for ( i=0; i<data->num_keys; i++ ) {
3295 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3296 data->keys[i].name));
3298 SAFE_FREE( data->keys[i].name );
3299 regval_ctr_destroy( &data->keys[i].values );
3302 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3303 p2->printername ));
3305 SAFE_FREE( data->keys );
3306 ZERO_STRUCTP( data );
3308 return WERR_OK;
3311 /* remove a specific key (and all subkeys) */
3313 for ( i=0; i<data->num_keys; i++ ) {
3314 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3315 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3316 data->keys[i].name));
3318 SAFE_FREE( data->keys[i].name );
3319 regval_ctr_destroy( &data->keys[i].values );
3321 /* mark the slot as empty */
3323 ZERO_STRUCTP( &data->keys[i] );
3327 /* find the first empty slot */
3329 for ( i=0; i<data->num_keys; i++ ) {
3330 if ( !data->keys[i].name ) {
3331 empty_slot = i;
3332 removed_keys++;
3333 break;
3337 if ( i == data->num_keys )
3338 /* nothing was removed */
3339 return WERR_INVALID_PARAM;
3341 /* move everything down */
3343 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3344 if ( data->keys[i].name ) {
3345 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3346 ZERO_STRUCTP( &data->keys[i] );
3347 empty_slot++;
3348 removed_keys++;
3352 /* update count */
3354 data->num_keys -= removed_keys;
3356 /* sanity check to see if anything is left */
3358 if ( !data->num_keys ) {
3359 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3361 SAFE_FREE( data->keys );
3362 ZERO_STRUCTP( data );
3365 return WERR_OK;
3368 /****************************************************************************
3369 ***************************************************************************/
3371 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3373 WERROR result = WERR_OK;
3374 int key_index;
3376 /* we must have names on non-zero length */
3378 if ( !key || !*key|| !value || !*value )
3379 return WERR_INVALID_NAME;
3381 /* find the printer key first */
3383 key_index = lookup_printerkey( &p2->data, key );
3384 if ( key_index == -1 )
3385 return WERR_OK;
3387 /* make sure the value exists so we can return the correct error code */
3389 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3390 return WERR_BADFILE;
3392 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3394 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3395 key, value ));
3397 return result;
3400 /****************************************************************************
3401 ***************************************************************************/
3403 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3404 uint32 type, uint8 *data, int real_len )
3406 WERROR result = WERR_OK;
3407 int key_index;
3409 /* we must have names on non-zero length */
3411 if ( !key || !*key|| !value || !*value )
3412 return WERR_INVALID_NAME;
3414 /* find the printer key first */
3416 key_index = lookup_printerkey( &p2->data, key );
3417 if ( key_index == -1 )
3418 key_index = add_new_printer_key( &p2->data, key );
3420 if ( key_index == -1 )
3421 return WERR_NOMEM;
3423 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3424 type, (const char *)data, real_len );
3426 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3427 key, value, type, real_len ));
3429 return result;
3432 /****************************************************************************
3433 ***************************************************************************/
3435 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3437 int key_index;
3439 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3440 return NULL;
3442 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3443 key, value ));
3445 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3448 /****************************************************************************
3449 Unpack a list of registry values frem the TDB
3450 ***************************************************************************/
3452 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3454 int len = 0;
3455 uint32 type;
3456 pstring string, valuename, keyname;
3457 char *str;
3458 int size;
3459 uint8 *data_p;
3460 REGISTRY_VALUE *regval_p;
3461 int key_index;
3463 /* add the "PrinterDriverData" key first for performance reasons */
3465 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3467 /* loop and unpack the rest of the registry values */
3469 while ( True ) {
3471 /* check to see if there are any more registry values */
3473 regval_p = NULL;
3474 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3475 if ( !regval_p )
3476 break;
3478 /* unpack the next regval */
3480 len += tdb_unpack(buf+len, buflen-len, "fdB",
3481 string,
3482 &type,
3483 &size,
3484 &data_p);
3486 /* lookup for subkey names which have a type of REG_NONE */
3487 /* there's no data with this entry */
3489 if ( type == REG_NONE ) {
3490 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3491 add_new_printer_key( printer_data, string );
3492 continue;
3496 * break of the keyname from the value name.
3497 * Valuenames can have embedded '\'s so be careful.
3498 * only support one level of keys. See the
3499 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3500 * -- jerry
3503 str = strchr_m( string, '\\');
3505 /* Put in "PrinterDriverData" is no key specified */
3507 if ( !str ) {
3508 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3509 pstrcpy( valuename, string );
3511 else {
3512 *str = '\0';
3513 pstrcpy( keyname, string );
3514 pstrcpy( valuename, str+1 );
3517 /* see if we need a new key */
3519 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3520 key_index = add_new_printer_key( printer_data, keyname );
3522 if ( key_index == -1 ) {
3523 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3524 keyname));
3525 break;
3528 /* add the new value */
3530 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3532 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3534 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3537 return len;
3540 /****************************************************************************
3541 ***************************************************************************/
3543 static void map_to_os2_driver(fstring drivername)
3545 static BOOL initialised=False;
3546 static fstring last_from,last_to;
3547 char *mapfile = lp_os2_driver_map();
3548 char **lines = NULL;
3549 int numlines = 0;
3550 int i;
3552 if (!strlen(drivername))
3553 return;
3555 if (!*mapfile)
3556 return;
3558 if (!initialised) {
3559 *last_from = *last_to = 0;
3560 initialised = True;
3563 if (strequal(drivername,last_from)) {
3564 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3565 fstrcpy(drivername,last_to);
3566 return;
3569 lines = file_lines_load(mapfile, &numlines);
3570 if (numlines == 0) {
3571 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3572 return;
3575 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3577 for( i = 0; i < numlines; i++) {
3578 char *nt_name = lines[i];
3579 char *os2_name = strchr(nt_name,'=');
3581 if (!os2_name)
3582 continue;
3584 *os2_name++ = 0;
3586 while (isspace(*nt_name))
3587 nt_name++;
3589 if (!*nt_name || strchr("#;",*nt_name))
3590 continue;
3593 int l = strlen(nt_name);
3594 while (l && isspace(nt_name[l-1])) {
3595 nt_name[l-1] = 0;
3596 l--;
3600 while (isspace(*os2_name))
3601 os2_name++;
3604 int l = strlen(os2_name);
3605 while (l && isspace(os2_name[l-1])) {
3606 os2_name[l-1] = 0;
3607 l--;
3611 if (strequal(nt_name,drivername)) {
3612 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3613 fstrcpy(last_from,drivername);
3614 fstrcpy(last_to,os2_name);
3615 fstrcpy(drivername,os2_name);
3616 file_lines_free(lines);
3617 return;
3621 file_lines_free(lines);
3624 /****************************************************************************
3625 Get a default printer info 2 struct.
3626 ****************************************************************************/
3627 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3629 int snum;
3630 NT_PRINTER_INFO_LEVEL_2 info;
3632 ZERO_STRUCT(info);
3634 snum = lp_servicenumber(sharename);
3636 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3637 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3638 servername, sharename);
3639 fstrcpy(info.sharename, sharename);
3640 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3642 /* by setting the driver name to an empty string, a local NT admin
3643 can now run the **local** APW to install a local printer driver
3644 for a Samba shared printer in 2.2. Without this, drivers **must** be
3645 installed on the Samba server for NT clients --jerry */
3646 #if 0 /* JERRY --do not uncomment-- */
3647 if (!*info.drivername)
3648 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3649 #endif
3652 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3654 pstrcpy(info.comment, "");
3655 fstrcpy(info.printprocessor, "winprint");
3656 fstrcpy(info.datatype, "RAW");
3658 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3660 info.starttime = 0; /* Minutes since 12:00am GMT */
3661 info.untiltime = 0; /* Minutes since 12:00am GMT */
3662 info.priority = 1;
3663 info.default_priority = 1;
3664 info.setuptime = (uint32)time(NULL);
3667 * I changed this as I think it is better to have a generic
3668 * DEVMODE than to crash Win2k explorer.exe --jerry
3669 * See the HP Deskjet 990c Win2k drivers for an example.
3671 * However the default devmode appears to cause problems
3672 * with the HP CLJ 8500 PCL driver. Hence the addition of
3673 * the "default devmode" parameter --jerry 22/01/2002
3676 if (lp_default_devmode(snum)) {
3677 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3678 goto fail;
3680 else {
3681 info.devmode = NULL;
3684 /* This will get the current RPC talloc context, but we should be
3685 passing this as a parameter... fixme... JRA ! */
3687 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3688 goto fail;
3690 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3691 if (! *info_ptr) {
3692 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3693 goto fail;
3696 return WERR_OK;
3698 fail:
3699 if (info.devmode)
3700 free_nt_devicemode(&info.devmode);
3701 return WERR_ACCESS_DENIED;
3704 /****************************************************************************
3705 ****************************************************************************/
3706 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3708 NT_PRINTER_INFO_LEVEL_2 info;
3709 int len = 0;
3710 int snum = lp_servicenumber(sharename);
3711 TDB_DATA kbuf, dbuf;
3712 fstring printername;
3713 char adevice[MAXDEVICENAME];
3715 ZERO_STRUCT(info);
3717 kbuf = make_printer_tdbkey( sharename );
3719 dbuf = tdb_fetch(tdb_printers, kbuf);
3720 if (!dbuf.dptr)
3721 return get_a_printer_2_default(info_ptr, servername, sharename);
3723 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3724 &info.attributes,
3725 &info.priority,
3726 &info.default_priority,
3727 &info.starttime,
3728 &info.untiltime,
3729 &info.status,
3730 &info.cjobs,
3731 &info.averageppm,
3732 &info.changeid,
3733 &info.c_setprinter,
3734 &info.setuptime,
3735 info.servername,
3736 info.printername,
3737 info.sharename,
3738 info.portname,
3739 info.drivername,
3740 info.comment,
3741 info.location,
3742 info.sepfile,
3743 info.printprocessor,
3744 info.datatype,
3745 info.parameters);
3747 /* Samba has to have shared raw drivers. */
3748 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3749 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3751 /* Restore the stripped strings. */
3752 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3754 if ( lp_force_printername(snum) )
3755 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3756 else
3757 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3759 fstrcpy(info.printername, printername);
3761 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3764 * Some client drivers freak out if there is a NULL devmode
3765 * (probably the driver is not checking before accessing
3766 * the devmode pointer) --jerry
3768 * See comments in get_a_printer_2_default()
3771 if (lp_default_devmode(snum) && !info.devmode) {
3772 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3773 printername));
3774 info.devmode = construct_nt_devicemode(printername);
3777 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3778 if (info.devmode) {
3779 fstrcpy(info.devmode->devicename, adevice);
3782 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3784 /* This will get the current RPC talloc context, but we should be
3785 passing this as a parameter... fixme... JRA ! */
3787 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3789 /* Fix for OS/2 drivers. */
3791 if (get_remote_arch() == RA_OS2)
3792 map_to_os2_driver(info.drivername);
3794 SAFE_FREE(dbuf.dptr);
3795 *info_ptr=memdup(&info, sizeof(info));
3797 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3798 sharename, info.printername, info.drivername));
3800 return WERR_OK;
3803 /****************************************************************************
3804 Debugging function, dump at level 6 the struct in the logs.
3805 ****************************************************************************/
3806 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3808 uint32 result;
3809 NT_PRINTER_INFO_LEVEL_2 *info2;
3811 DEBUG(106,("Dumping printer at level [%d]\n", level));
3813 switch (level) {
3814 case 2:
3816 if (printer->info_2 == NULL)
3817 result=5;
3818 else
3820 info2=printer->info_2;
3822 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3823 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3824 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3825 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3826 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3827 DEBUGADD(106,("status:[%d]\n", info2->status));
3828 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3829 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3830 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3831 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3832 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3834 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3835 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3836 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3837 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3838 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3839 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3840 DEBUGADD(106,("location:[%s]\n", info2->location));
3841 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3842 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3843 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3844 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3845 result=0;
3847 break;
3849 default:
3850 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3851 result=1;
3852 break;
3855 return result;
3858 /****************************************************************************
3859 Update the changeid time.
3860 This is SO NASTY as some drivers need this to change, others need it
3861 static. This value will change every second, and I must hope that this
3862 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3863 UTAH ! JRA.
3864 ****************************************************************************/
3866 static uint32 rev_changeid(void)
3868 struct timeval tv;
3870 get_process_uptime(&tv);
3872 #if 1 /* JERRY */
3873 /* Return changeid as msec since spooler restart */
3874 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3875 #else
3877 * This setting seems to work well but is too untested
3878 * to replace the above calculation. Left in for experiementation
3879 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3881 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3882 #endif
3885 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
3886 /********************************************************************
3887 Send a message to all smbds about the printer that just changed
3888 ********************************************************************/
3890 static BOOL send_printer_mod_msg( char* printername )
3892 int len = strlen(printername);
3894 if (!len)
3895 return False;
3897 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3898 printername));
3900 /* spam everyone that we just changed this printer */
3902 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3904 return True;
3906 #endif
3910 * The function below are the high level ones.
3911 * only those ones must be called from the spoolss code.
3912 * JFM.
3915 /****************************************************************************
3916 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3917 ****************************************************************************/
3919 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3921 WERROR result;
3923 dump_a_printer(printer, level);
3925 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
3927 * invalidate cache for all open handles to this printer.
3928 * cache for a given handle will be updated on the next
3929 * get_a_printer()
3932 invalidate_printer_hnd_cache( printer->info_2->sharename );
3934 /* messages between smbds can only be sent as root */
3935 become_root();
3936 send_printer_mod_msg( printer->info_2->sharename );
3937 unbecome_root();
3938 #endif
3940 switch (level) {
3941 case 2:
3944 * Update the changestamp. Emperical tests show that the
3945 * ChangeID is always updated,but c_setprinter is
3946 * global spooler variable (not per printer).
3949 /* ChangeID **must** be increasing over the lifetime
3950 of client's spoolss service in order for the
3951 client's cache to show updates */
3953 printer->info_2->changeid = rev_changeid();
3956 * Because one day someone will ask:
3957 * NT->NT An admin connection to a remote
3958 * printer show changes imeediately in
3959 * the properities dialog
3961 * A non-admin connection will only show the
3962 * changes after viewing the properites page
3963 * 2 times. Seems to be related to a
3964 * race condition in the client between the spooler
3965 * updating the local cache and the Explorer.exe GUI
3966 * actually displaying the properties.
3968 * This is fixed in Win2k. admin/non-admin
3969 * connections both display changes immediately.
3971 * 14/12/01 --jerry
3974 result=update_a_printer_2(printer->info_2);
3976 break;
3978 default:
3979 result=WERR_UNKNOWN_LEVEL;
3980 break;
3983 return result;
3986 /****************************************************************************
3987 Initialize printer devmode & data with previously saved driver init values.
3988 ****************************************************************************/
3990 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3992 int len = 0;
3993 pstring key;
3994 TDB_DATA kbuf, dbuf;
3995 NT_PRINTER_INFO_LEVEL_2 info;
3998 ZERO_STRUCT(info);
4001 * Delete any printer data 'values' already set. When called for driver
4002 * replace, there will generally be some, but during an add printer, there
4003 * should not be any (if there are delete them).
4006 delete_all_printer_data( info_ptr, "" );
4008 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4010 kbuf.dptr = key;
4011 kbuf.dsize = strlen(key)+1;
4013 dbuf = tdb_fetch(tdb_drivers, kbuf);
4014 if (!dbuf.dptr) {
4016 * When changing to a driver that has no init info in the tdb, remove
4017 * the previous drivers init info and leave the new on blank.
4019 free_nt_devicemode(&info_ptr->devmode);
4020 return False;
4024 * Get the saved DEVMODE..
4027 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4030 * The saved DEVMODE contains the devicename from the printer used during
4031 * the initialization save. Change it to reflect the new printer.
4034 if ( info.devmode ) {
4035 ZERO_STRUCT(info.devmode->devicename);
4036 fstrcpy(info.devmode->devicename, info_ptr->printername);
4040 * NT/2k does not change out the entire DeviceMode of a printer
4041 * when changing the driver. Only the driverextra, private, &
4042 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4044 * Later examination revealed that Windows NT/2k does reset the
4045 * the printer's device mode, bit **only** when you change a
4046 * property of the device mode such as the page orientation.
4047 * --jerry
4051 /* Bind the saved DEVMODE to the new the printer */
4053 free_nt_devicemode(&info_ptr->devmode);
4054 info_ptr->devmode = info.devmode;
4056 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4057 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4059 /* Add the printer data 'values' to the new printer */
4061 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4064 SAFE_FREE(dbuf.dptr);
4066 return True;
4069 /****************************************************************************
4070 Initialize printer devmode & data with previously saved driver init values.
4071 When a printer is created using AddPrinter, the drivername bound to the
4072 printer is used to lookup previously saved driver initialization info, which
4073 is bound to the new printer.
4074 ****************************************************************************/
4076 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4078 BOOL result = False;
4080 switch (level) {
4081 case 2:
4082 result = set_driver_init_2(printer->info_2);
4083 break;
4085 default:
4086 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4087 level));
4088 break;
4091 return result;
4094 /****************************************************************************
4095 Delete driver init data stored for a specified driver
4096 ****************************************************************************/
4098 BOOL del_driver_init(char *drivername)
4100 pstring key;
4101 TDB_DATA kbuf;
4103 if (!drivername || !*drivername) {
4104 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4105 return False;
4108 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4110 kbuf.dptr = key;
4111 kbuf.dsize = strlen(key)+1;
4113 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4115 return (tdb_delete(tdb_drivers, kbuf) == 0);
4118 /****************************************************************************
4119 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4120 in the tdb. Note: this is different from the driver entry and the printer
4121 entry. There should be a single driver init entry for each driver regardless
4122 of whether it was installed from NT or 2K. Technically, they should be
4123 different, but they work out to the same struct.
4124 ****************************************************************************/
4126 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4128 pstring key;
4129 char *buf;
4130 int buflen, len, ret;
4131 TDB_DATA kbuf, dbuf;
4133 buf = NULL;
4134 buflen = 0;
4136 again:
4137 len = 0;
4138 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4140 len += pack_values( &info->data, buf+len, buflen-len );
4142 if (buflen < len) {
4143 char *tb;
4145 tb = (char *)SMB_REALLOC(buf, len);
4146 if (!tb) {
4147 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4148 ret = -1;
4149 goto done;
4151 else
4152 buf = tb;
4153 buflen = len;
4154 goto again;
4157 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4159 kbuf.dptr = key;
4160 kbuf.dsize = strlen(key)+1;
4161 dbuf.dptr = buf;
4162 dbuf.dsize = len;
4164 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4166 done:
4167 if (ret == -1)
4168 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4170 SAFE_FREE(buf);
4172 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4173 info->sharename, info->drivername));
4175 return ret;
4178 /****************************************************************************
4179 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4180 ****************************************************************************/
4182 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4184 uint32 result;
4186 dump_a_printer(printer, level);
4188 switch (level) {
4189 case 2:
4190 result = update_driver_init_2(printer->info_2);
4191 break;
4192 default:
4193 result = 1;
4194 break;
4197 return result;
4200 /****************************************************************************
4201 Convert the printer data value, a REG_BINARY array, into an initialization
4202 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4203 got to keep the endians happy :).
4204 ****************************************************************************/
4206 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4208 BOOL result = False;
4209 prs_struct ps;
4210 DEVICEMODE devmode;
4212 ZERO_STRUCT(devmode);
4214 prs_init(&ps, 0, ctx, UNMARSHALL);
4215 ps.data_p = (char *)data;
4216 ps.buffer_size = data_len;
4218 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4219 result = convert_devicemode("", &devmode, &nt_devmode);
4220 else
4221 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4223 return result;
4226 /****************************************************************************
4227 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4229 1. Use the driver's config DLL to this UNC printername and:
4230 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4231 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4232 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4234 The last step triggers saving the "driver initialization" information for
4235 this printer into the tdb. Later, new printers that use this driver will
4236 have this initialization information bound to them. This simulates the
4237 driver initialization, as if it had run on the Samba server (as it would
4238 have done on NT).
4240 The Win32 client side code requirement sucks! But until we can run arbitrary
4241 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4243 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4244 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4245 about it and you will realize why. JRR 010720
4246 ****************************************************************************/
4248 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4250 WERROR status = WERR_OK;
4251 TALLOC_CTX *ctx = NULL;
4252 NT_DEVICEMODE *nt_devmode = NULL;
4253 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4256 * When the DEVMODE is already set on the printer, don't try to unpack it.
4258 DEBUG(8,("save_driver_init_2: Enter...\n"));
4260 if ( !printer->info_2->devmode && data_len ) {
4262 * Set devmode on printer info, so entire printer initialization can be
4263 * saved to tdb.
4266 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4267 return WERR_NOMEM;
4269 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4270 status = WERR_NOMEM;
4271 goto done;
4274 ZERO_STRUCTP(nt_devmode);
4277 * The DEVMODE is held in the 'data' component of the param in raw binary.
4278 * Convert it to to a devmode structure
4280 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4281 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4282 status = WERR_INVALID_PARAM;
4283 goto done;
4286 printer->info_2->devmode = nt_devmode;
4290 * Pack up and add (or update) the DEVMODE and any current printer data to
4291 * a 'driver init' element in the tdb
4295 if ( update_driver_init(printer, 2) != 0 ) {
4296 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4297 status = WERR_NOMEM;
4298 goto done;
4302 * If driver initialization info was successfully saved, set the current
4303 * printer to match it. This allows initialization of the current printer
4304 * as well as the driver.
4306 status = mod_a_printer(printer, 2);
4307 if (!W_ERROR_IS_OK(status)) {
4308 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4309 printer->info_2->printername));
4312 done:
4313 talloc_destroy(ctx);
4314 free_nt_devicemode( &nt_devmode );
4316 printer->info_2->devmode = tmp_devmode;
4318 return status;
4321 /****************************************************************************
4322 Update the driver init info (DEVMODE and specifics) for a printer
4323 ****************************************************************************/
4325 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4327 WERROR status = WERR_OK;
4329 switch (level) {
4330 case 2:
4331 status = save_driver_init_2( printer, data, data_len );
4332 break;
4333 default:
4334 status = WERR_UNKNOWN_LEVEL;
4335 break;
4338 return status;
4341 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4342 /****************************************************************************
4343 Deep copy a NT_PRINTER_DATA
4344 ****************************************************************************/
4346 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4348 int i, j, num_vals, new_key_index;
4349 REGVAL_CTR *src_key, *dst_key;
4351 if ( !dst || !src )
4352 return NT_STATUS_NO_MEMORY;
4354 for ( i=0; i<src->num_keys; i++ ) {
4356 /* create a new instance of the printerkey in the destination
4357 printer_data object */
4359 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4360 dst_key = &dst->keys[new_key_index].values;
4362 src_key = &src->keys[i].values;
4363 num_vals = regval_ctr_numvals( src_key );
4365 /* dup the printer entire printer key */
4367 for ( j=0; j<num_vals; j++ ) {
4368 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4372 return NT_STATUS_OK;
4375 /****************************************************************************
4376 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4377 Caller must free.
4378 ****************************************************************************/
4380 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4382 NT_PRINTER_INFO_LEVEL_2 *copy;
4384 if ( !printer )
4385 return NULL;
4387 if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4388 return NULL;
4390 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4392 /* malloc()'d members copied here */
4394 copy->devmode = dup_nt_devicemode( printer->devmode );
4396 ZERO_STRUCT( copy->data );
4397 copy_printer_data( &copy->data, &printer->data );
4399 /* this is talloc()'d; very ugly that we have a structure that
4400 is half malloc()'d and half talloc()'d but that is the way
4401 that the PRINTER_INFO stuff is written right now. --jerry */
4403 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4405 return copy;
4407 #endif
4409 /****************************************************************************
4410 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4412 Previously the code had a memory allocation problem because it always
4413 used the TALLOC_CTX from the Printer_entry*. This context lasts
4414 as a long as the original handle is open. So if the client made a lot
4415 of getprinter[data]() calls, the memory usage would climb. Now we use
4416 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4417 still use the Printer_entry->ctx for maintaining the cache copy though
4418 since that object must live as long as the handle by definition.
4419 --jerry
4421 ****************************************************************************/
4423 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4424 const char *sharename)
4426 WERROR result;
4427 NT_PRINTER_INFO_LEVEL *printer = NULL;
4428 fstring servername;
4430 *pp_printer = NULL;
4432 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4434 switch (level) {
4435 case 2:
4436 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4437 DEBUG(0,("get_a_printer: malloc fail.\n"));
4438 return WERR_NOMEM;
4440 ZERO_STRUCTP(printer);
4442 if ( print_hnd )
4443 fstrcpy( servername, print_hnd->servername );
4444 else {
4445 fstrcpy( servername, "%L" );
4446 standard_sub_basic( "", servername, sizeof(servername)-1 );
4449 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4452 * check for cache first. A Printer handle cannot changed
4453 * to another printer object so we only check that the printer
4454 * is actually for a printer and that the printer_info pointer
4455 * is valid
4457 if ( print_hnd
4458 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4459 && print_hnd->printer_info )
4461 /* get_talloc_ctx() works here because we need a short
4462 lived talloc context */
4464 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4466 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4468 SAFE_FREE(printer);
4469 return WERR_NOMEM;
4472 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4474 *pp_printer = printer;
4475 result = WERR_OK;
4477 break;
4480 /* no cache for this handle; see if we can match one from another handle.
4481 Make sure to use a short lived talloc ctx */
4483 if ( print_hnd )
4484 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4486 /* fail to disk if we don't have it with any open handle */
4488 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4489 result = get_a_printer_2(&printer->info_2, servername, sharename );
4490 #else
4491 result = get_a_printer_2(&printer->info_2, servername, sharename );
4492 #endif
4495 /* we have a new printer now. Save it with this handle */
4497 if ( W_ERROR_IS_OK(result) ) {
4498 dump_a_printer(printer, level);
4500 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4501 /* save a copy in cache */
4502 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4503 if ( !print_hnd->printer_info )
4504 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4506 if ( print_hnd->printer_info ) {
4507 /* make sure to use the handle's talloc ctx here since
4508 the printer_2 object must last until the handle is closed */
4510 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4512 /* don't fail the lookup just because the cache update failed */
4513 if ( !print_hnd->printer_info->info_2 )
4514 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4517 #endif
4518 *pp_printer = printer;
4520 else
4521 SAFE_FREE(printer);
4523 break;
4525 default:
4526 result=WERR_UNKNOWN_LEVEL;
4527 break;
4530 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4532 return result;
4535 /****************************************************************************
4536 Deletes a NT_PRINTER_INFO_LEVEL struct.
4537 ****************************************************************************/
4539 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4541 uint32 result;
4542 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4544 DEBUG(104,("freeing a printer at level [%d]\n", level));
4546 if (printer == NULL)
4547 return 0;
4549 switch (level) {
4550 case 2:
4551 if (printer->info_2 != NULL) {
4552 free_nt_printer_info_level_2(&printer->info_2);
4553 result=0;
4554 } else
4555 result=4;
4556 break;
4558 default:
4559 result=1;
4560 break;
4563 SAFE_FREE(*pp_printer);
4564 return result;
4567 /****************************************************************************
4568 ****************************************************************************/
4569 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4571 uint32 result;
4572 DEBUG(104,("adding a printer at level [%d]\n", level));
4573 dump_a_printer_driver(driver, level);
4575 switch (level) {
4576 case 3:
4577 result=add_a_printer_driver_3(driver.info_3);
4578 break;
4580 case 6:
4581 result=add_a_printer_driver_6(driver.info_6);
4582 break;
4584 default:
4585 result=1;
4586 break;
4589 return result;
4591 /****************************************************************************
4592 ****************************************************************************/
4594 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4595 fstring drivername, const char *architecture, uint32 version)
4597 WERROR result;
4599 switch (level) {
4600 case 3:
4601 /* Sometime we just want any version of the driver */
4603 if ( version == DRIVER_ANY_VERSION ) {
4604 /* look for Win2k first and then for NT4 */
4605 result = get_a_printer_driver_3(&driver->info_3, drivername,
4606 architecture, 3);
4608 if ( !W_ERROR_IS_OK(result) ) {
4609 result = get_a_printer_driver_3( &driver->info_3,
4610 drivername, architecture, 2 );
4612 } else {
4613 result = get_a_printer_driver_3(&driver->info_3, drivername,
4614 architecture, version);
4616 break;
4618 default:
4619 result=W_ERROR(1);
4620 break;
4623 if (W_ERROR_IS_OK(result))
4624 dump_a_printer_driver(*driver, level);
4626 return result;
4629 /****************************************************************************
4630 ****************************************************************************/
4631 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4633 uint32 result;
4635 switch (level) {
4636 case 3:
4638 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4639 if (driver.info_3 != NULL)
4641 info3=driver.info_3;
4642 SAFE_FREE(info3->dependentfiles);
4643 ZERO_STRUCTP(info3);
4644 SAFE_FREE(info3);
4645 result=0;
4646 } else {
4647 result=4;
4649 break;
4651 case 6:
4653 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4654 if (driver.info_6 != NULL) {
4655 info6=driver.info_6;
4656 SAFE_FREE(info6->dependentfiles);
4657 SAFE_FREE(info6->previousnames);
4658 ZERO_STRUCTP(info6);
4659 SAFE_FREE(info6);
4660 result=0;
4661 } else {
4662 result=4;
4664 break;
4666 default:
4667 result=1;
4668 break;
4670 return result;
4674 /****************************************************************************
4675 Determine whether or not a particular driver is currently assigned
4676 to a printer
4677 ****************************************************************************/
4679 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4681 int snum;
4682 int n_services = lp_numservices();
4683 NT_PRINTER_INFO_LEVEL *printer = NULL;
4684 BOOL in_use = False;
4686 if ( !info_3 )
4687 return False;
4689 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4691 /* loop through the printers.tdb and check for the drivername */
4693 for (snum=0; snum<n_services && !in_use; snum++) {
4694 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4695 continue;
4697 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4698 continue;
4700 if ( strequal(info_3->name, printer->info_2->drivername) )
4701 in_use = True;
4703 free_a_printer( &printer, 2 );
4706 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4708 if ( in_use ) {
4709 NT_PRINTER_DRIVER_INFO_LEVEL d;
4710 WERROR werr;
4712 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4714 /* we can still remove the driver if there is one of
4715 "Windows NT x86" version 2 or 3 left */
4717 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4718 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4720 else {
4721 switch ( info_3->cversion ) {
4722 case 2:
4723 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4724 break;
4725 case 3:
4726 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4727 break;
4728 default:
4729 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4730 info_3->cversion));
4731 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4732 break;
4736 /* now check the error code */
4738 if ( W_ERROR_IS_OK(werr) ) {
4739 /* it's ok to remove the driver, we have other architctures left */
4740 in_use = False;
4741 free_a_printer_driver( d, 3 );
4745 /* report that the driver is not in use by default */
4747 return in_use;
4751 /**********************************************************************
4752 Check to see if a ogiven file is in use by *info
4753 *********************************************************************/
4755 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4757 int i = 0;
4759 if ( !info )
4760 return False;
4762 if ( strequal(file, info->driverpath) )
4763 return True;
4765 if ( strequal(file, info->datafile) )
4766 return True;
4768 if ( strequal(file, info->configfile) )
4769 return True;
4771 if ( strequal(file, info->helpfile) )
4772 return True;
4774 /* see of there are any dependent files to examine */
4776 if ( !info->dependentfiles )
4777 return False;
4779 while ( *info->dependentfiles[i] ) {
4780 if ( strequal(file, info->dependentfiles[i]) )
4781 return True;
4782 i++;
4785 return False;
4789 /**********************************************************************
4790 Utility function to remove the dependent file pointed to by the
4791 input parameter from the list
4792 *********************************************************************/
4794 static void trim_dependent_file( fstring files[], int idx )
4797 /* bump everything down a slot */
4799 while( *files[idx+1] ) {
4800 fstrcpy( files[idx], files[idx+1] );
4801 idx++;
4804 *files[idx] = '\0';
4806 return;
4809 /**********************************************************************
4810 Check if any of the files used by src are also used by drv
4811 *********************************************************************/
4813 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4814 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4816 BOOL in_use = False;
4817 int i = 0;
4819 if ( !src || !drv )
4820 return False;
4822 /* check each file. Remove it from the src structure if it overlaps */
4824 if ( drv_file_in_use(src->driverpath, drv) ) {
4825 in_use = True;
4826 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4827 fstrcpy( src->driverpath, "" );
4830 if ( drv_file_in_use(src->datafile, drv) ) {
4831 in_use = True;
4832 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4833 fstrcpy( src->datafile, "" );
4836 if ( drv_file_in_use(src->configfile, drv) ) {
4837 in_use = True;
4838 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4839 fstrcpy( src->configfile, "" );
4842 if ( drv_file_in_use(src->helpfile, drv) ) {
4843 in_use = True;
4844 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4845 fstrcpy( src->helpfile, "" );
4848 /* are there any dependentfiles to examine? */
4850 if ( !src->dependentfiles )
4851 return in_use;
4853 while ( *src->dependentfiles[i] ) {
4854 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4855 in_use = True;
4856 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4857 trim_dependent_file( src->dependentfiles, i );
4858 } else
4859 i++;
4862 return in_use;
4865 /****************************************************************************
4866 Determine whether or not a particular driver files are currently being
4867 used by any other driver.
4869 Return value is True if any files were in use by other drivers
4870 and False otherwise.
4872 Upon return, *info has been modified to only contain the driver files
4873 which are not in use
4874 ****************************************************************************/
4876 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4878 int i;
4879 int ndrivers;
4880 uint32 version;
4881 fstring *list = NULL;
4882 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4884 if ( !info )
4885 return False;
4887 version = info->cversion;
4889 /* loop over all driver versions */
4891 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4893 /* get the list of drivers */
4895 list = NULL;
4896 ndrivers = get_ntdrivers(&list, info->environment, version);
4898 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4899 ndrivers, info->environment, version));
4901 /* check each driver for overlap in files */
4903 for (i=0; i<ndrivers; i++) {
4904 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4906 ZERO_STRUCT(driver);
4908 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4909 SAFE_FREE(list);
4910 return True;
4913 /* check if d2 uses any files from d1 */
4914 /* only if this is a different driver than the one being deleted */
4916 if ( !strequal(info->name, driver.info_3->name) ) {
4917 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4918 free_a_printer_driver(driver, 3);
4919 SAFE_FREE( list );
4920 return True;
4924 free_a_printer_driver(driver, 3);
4927 SAFE_FREE(list);
4929 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4931 driver.info_3 = info;
4933 if ( DEBUGLEVEL >= 20 )
4934 dump_a_printer_driver( driver, 3 );
4936 return False;
4939 /****************************************************************************
4940 Actually delete the driver files. Make sure that
4941 printer_driver_files_in_use() return False before calling
4942 this.
4943 ****************************************************************************/
4945 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4947 int i = 0;
4948 char *s;
4949 pstring file;
4950 connection_struct *conn;
4951 DATA_BLOB null_pw;
4952 NTSTATUS nt_status;
4953 fstring res_type;
4954 BOOL bad_path;
4955 SMB_STRUCT_STAT st;
4957 if ( !info_3 )
4958 return False;
4960 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4963 * Connect to the print$ share under the same account as the
4964 * user connected to the rpc pipe. Note we must be root to
4965 * do this.
4968 null_pw = data_blob( NULL, 0 );
4969 fstrcpy(res_type, "A:");
4970 become_root();
4971 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4972 unbecome_root();
4974 if ( !conn ) {
4975 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4976 return False;
4979 /* Save who we are - we are temporarily becoming the connection user. */
4981 if ( !become_user(conn, conn->vuid) ) {
4982 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4983 return False;
4986 /* now delete the files; must strip the '\print$' string from
4987 fron of path */
4989 if ( *info_3->driverpath ) {
4990 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4991 pstrcpy( file, s );
4992 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4993 DEBUG(10,("deleting driverfile [%s]\n", s));
4994 unlink_internals(conn, 0, file);
4998 if ( *info_3->configfile ) {
4999 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
5000 pstrcpy( file, s );
5001 driver_unix_convert(file, conn, NULL, &bad_path, &st);
5002 DEBUG(10,("deleting configfile [%s]\n", s));
5003 unlink_internals(conn, 0, file);
5007 if ( *info_3->datafile ) {
5008 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
5009 pstrcpy( file, s );
5010 driver_unix_convert(file, conn, NULL, &bad_path, &st);
5011 DEBUG(10,("deleting datafile [%s]\n", s));
5012 unlink_internals(conn, 0, file);
5016 if ( *info_3->helpfile ) {
5017 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
5018 pstrcpy( file, s );
5019 driver_unix_convert(file, conn, NULL, &bad_path, &st);
5020 DEBUG(10,("deleting helpfile [%s]\n", s));
5021 unlink_internals(conn, 0, file);
5025 /* check if we are done removing files */
5027 if ( info_3->dependentfiles ) {
5028 while ( info_3->dependentfiles[i][0] ) {
5029 char *p;
5031 /* bypass the "\print$" portion of the path */
5033 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
5034 pstrcpy( file, p );
5035 driver_unix_convert(file, conn, NULL, &bad_path, &st);
5036 DEBUG(10,("deleting dependent file [%s]\n", file));
5037 unlink_internals(conn, 0, file );
5040 i++;
5044 unbecome_user();
5046 return True;
5049 /****************************************************************************
5050 Remove a printer driver from the TDB. This assumes that the the driver was
5051 previously looked up.
5052 ***************************************************************************/
5054 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5055 uint32 version, BOOL delete_files )
5057 pstring key;
5058 const char *arch;
5059 TDB_DATA kbuf, dbuf;
5060 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5062 /* delete the tdb data first */
5064 arch = get_short_archi(info_3->environment);
5065 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5066 arch, version, info_3->name);
5068 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5069 key, delete_files ? "TRUE" : "FALSE" ));
5071 ctr.info_3 = info_3;
5072 dump_a_printer_driver( ctr, 3 );
5074 kbuf.dptr=key;
5075 kbuf.dsize=strlen(key)+1;
5077 /* check if the driver actually exists for this environment */
5079 dbuf = tdb_fetch( tdb_drivers, kbuf );
5080 if ( !dbuf.dptr ) {
5081 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5082 return WERR_UNKNOWN_PRINTER_DRIVER;
5085 SAFE_FREE( dbuf.dptr );
5087 /* ok... the driver exists so the delete should return success */
5089 if (tdb_delete(tdb_drivers, kbuf) == -1) {
5090 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5091 return WERR_ACCESS_DENIED;
5095 * now delete any associated files if delete_files == True
5096 * even if this part failes, we return succes because the
5097 * driver doesn not exist any more
5100 if ( delete_files )
5101 delete_driver_files( info_3, user );
5104 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5106 return WERR_OK;
5109 /****************************************************************************
5110 Store a security desc for a printer.
5111 ****************************************************************************/
5113 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5115 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5116 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5117 prs_struct ps;
5118 TALLOC_CTX *mem_ctx = NULL;
5119 char *key;
5120 WERROR status;
5122 mem_ctx = talloc_init("nt_printing_setsec");
5123 if (mem_ctx == NULL)
5124 return WERR_NOMEM;
5126 /* The old owner and group sids of the security descriptor are not
5127 present when new ACEs are added or removed by changing printer
5128 permissions through NT. If they are NULL in the new security
5129 descriptor then copy them over from the old one. */
5131 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
5132 DOM_SID *owner_sid, *group_sid;
5133 SEC_ACL *dacl, *sacl;
5134 SEC_DESC *psd = NULL;
5135 size_t size;
5137 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
5139 /* Pick out correct owner and group sids */
5141 owner_sid = secdesc_ctr->sec->owner_sid ?
5142 secdesc_ctr->sec->owner_sid :
5143 old_secdesc_ctr->sec->owner_sid;
5145 group_sid = secdesc_ctr->sec->grp_sid ?
5146 secdesc_ctr->sec->grp_sid :
5147 old_secdesc_ctr->sec->grp_sid;
5149 dacl = secdesc_ctr->sec->dacl ?
5150 secdesc_ctr->sec->dacl :
5151 old_secdesc_ctr->sec->dacl;
5153 sacl = secdesc_ctr->sec->sacl ?
5154 secdesc_ctr->sec->sacl :
5155 old_secdesc_ctr->sec->sacl;
5157 /* Make a deep copy of the security descriptor */
5159 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
5160 owner_sid, group_sid,
5161 sacl,
5162 dacl,
5163 &size);
5165 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5168 if (!new_secdesc_ctr) {
5169 new_secdesc_ctr = secdesc_ctr;
5172 /* Store the security descriptor in a tdb */
5174 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
5175 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5177 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5178 &ps, 1)) {
5179 status = WERR_BADFUNC;
5180 goto out;
5183 key = make_printers_secdesc_tdbkey( sharename );
5185 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
5186 status = WERR_OK;
5187 } else {
5188 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5189 status = WERR_BADFUNC;
5192 /* Free malloc'ed memory */
5194 out:
5196 prs_mem_free(&ps);
5197 if (mem_ctx)
5198 talloc_destroy(mem_ctx);
5199 return status;
5202 /****************************************************************************
5203 Construct a default security descriptor buffer for a printer.
5204 ****************************************************************************/
5206 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5208 SEC_ACE ace[5]; /* max number of ace entries */
5209 int i = 0;
5210 SEC_ACCESS sa;
5211 SEC_ACL *psa = NULL;
5212 SEC_DESC_BUF *sdb = NULL;
5213 SEC_DESC *psd = NULL;
5214 DOM_SID adm_sid;
5215 size_t sd_size;
5217 /* Create an ACE where Everyone is allowed to print */
5219 init_sec_access(&sa, PRINTER_ACE_PRINT);
5220 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5221 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5223 /* Add the domain admins group if we are a DC */
5225 if ( IS_DC ) {
5226 DOM_SID domadmins_sid;
5228 sid_copy(&domadmins_sid, get_global_sam_sid());
5229 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5231 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5232 init_sec_ace(&ace[i++], &domadmins_sid,
5233 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5234 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5235 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5236 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5238 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5239 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5241 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5242 init_sec_ace(&ace[i++], &adm_sid,
5243 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5244 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5245 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5246 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5249 /* add BUILTIN\Administrators as FULL CONTROL */
5251 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5252 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5253 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5254 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5255 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5256 SEC_ACE_TYPE_ACCESS_ALLOWED,
5257 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5259 /* Make the security descriptor owned by the BUILTIN\Administrators */
5261 /* The ACL revision number in rpc_secdesc.h differs from the one
5262 created by NT when setting ACE entries in printer
5263 descriptors. NT4 complains about the property being edited by a
5264 NT5 machine. */
5266 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5267 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5268 &global_sid_Builtin_Administrators,
5269 &global_sid_Builtin_Administrators,
5270 NULL, psa, &sd_size);
5273 if (!psd) {
5274 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5275 return NULL;
5278 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5280 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5281 (unsigned int)sd_size));
5283 return sdb;
5286 /****************************************************************************
5287 Get a security desc for a printer.
5288 ****************************************************************************/
5290 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5292 prs_struct ps;
5293 char *key;
5294 char *temp;
5296 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5297 sharename = temp + 1;
5300 /* Fetch security descriptor from tdb */
5302 key = make_printers_secdesc_tdbkey( sharename );
5304 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5305 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5307 DEBUG(4,("using default secdesc for %s\n", sharename));
5309 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5310 return False;
5313 /* Save default security descriptor for later */
5315 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5316 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5318 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5319 tdb_prs_store(tdb_printers, key, &ps);
5321 prs_mem_free(&ps);
5323 return True;
5326 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5327 this security descriptor has been created when winbindd was
5328 down. Take ownership of security descriptor. */
5330 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5331 DOM_SID owner_sid;
5333 /* Change sd owner to workgroup administrator */
5335 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5336 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5337 SEC_DESC *psd = NULL;
5338 size_t size;
5340 /* Create new sd */
5342 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5344 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5345 &owner_sid,
5346 (*secdesc_ctr)->sec->grp_sid,
5347 (*secdesc_ctr)->sec->sacl,
5348 (*secdesc_ctr)->sec->dacl,
5349 &size);
5351 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5353 /* Swap with other one */
5355 *secdesc_ctr = new_secdesc_ctr;
5357 /* Set it */
5359 nt_printing_setsec(sharename, *secdesc_ctr);
5363 if (DEBUGLEVEL >= 10) {
5364 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5365 int i;
5367 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5368 sharename, the_acl->num_aces));
5370 for (i = 0; i < the_acl->num_aces; i++) {
5371 fstring sid_str;
5373 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5375 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5376 the_acl->ace[i].type, the_acl->ace[i].flags,
5377 the_acl->ace[i].info.mask));
5381 prs_mem_free(&ps);
5382 return True;
5385 /* error code:
5386 0: everything OK
5387 1: level not implemented
5388 2: file doesn't exist
5389 3: can't allocate memory
5390 4: can't free memory
5391 5: non existant struct
5395 A printer and a printer driver are 2 different things.
5396 NT manages them separatelly, Samba does the same.
5397 Why ? Simply because it's easier and it makes sense !
5399 Now explanation: You have 3 printers behind your samba server,
5400 2 of them are the same make and model (laser A and B). But laser B
5401 has an 3000 sheet feeder and laser A doesn't such an option.
5402 Your third printer is an old dot-matrix model for the accounting :-).
5404 If the /usr/local/samba/lib directory (default dir), you will have
5405 5 files to describe all of this.
5407 3 files for the printers (1 by printer):
5408 NTprinter_laser A
5409 NTprinter_laser B
5410 NTprinter_accounting
5411 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5412 NTdriver_printer model X
5413 NTdriver_printer model Y
5415 jfm: I should use this comment for the text file to explain
5416 same thing for the forms BTW.
5417 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5421 /* Convert generic access rights to printer object specific access rights.
5422 It turns out that NT4 security descriptors use generic access rights and
5423 NT5 the object specific ones. */
5425 void map_printer_permissions(SEC_DESC *sd)
5427 int i;
5429 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5430 se_map_generic(&sd->dacl->ace[i].info.mask,
5431 &printer_generic_mapping);
5435 /****************************************************************************
5436 Check a user has permissions to perform the given operation. We use the
5437 permission constants defined in include/rpc_spoolss.h to check the various
5438 actions we perform when checking printer access.
5440 PRINTER_ACCESS_ADMINISTER:
5441 print_queue_pause, print_queue_resume, update_printer_sec,
5442 update_printer, spoolss_addprinterex_level_2,
5443 _spoolss_setprinterdata
5445 PRINTER_ACCESS_USE:
5446 print_job_start
5448 JOB_ACCESS_ADMINISTER:
5449 print_job_delete, print_job_pause, print_job_resume,
5450 print_queue_purge
5452 Try access control in the following order (for performance reasons):
5453 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5454 2) check security descriptor (bit comparisons in memory)
5455 3) "printer admins" (may result in numerous calls to winbind)
5457 ****************************************************************************/
5458 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5460 SEC_DESC_BUF *secdesc = NULL;
5461 uint32 access_granted;
5462 NTSTATUS status;
5463 BOOL result;
5464 const char *pname;
5465 TALLOC_CTX *mem_ctx = NULL;
5466 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5468 /* If user is NULL then use the current_user structure */
5470 if (!user)
5471 user = &current_user;
5473 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5475 if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5476 return True;
5479 /* Get printer name */
5481 pname = PRINTERNAME(snum);
5483 if (!pname || !*pname) {
5484 errno = EACCES;
5485 return False;
5488 /* Get printer security descriptor */
5490 if(!(mem_ctx = talloc_init("print_access_check"))) {
5491 errno = ENOMEM;
5492 return False;
5495 nt_printing_getsec(mem_ctx, pname, &secdesc);
5497 if (access_type == JOB_ACCESS_ADMINISTER) {
5498 SEC_DESC_BUF *parent_secdesc = secdesc;
5500 /* Create a child security descriptor to check permissions
5501 against. This is because print jobs are child objects
5502 objects of a printer. */
5504 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5506 /* Now this is the bit that really confuses me. The access
5507 type needs to be changed from JOB_ACCESS_ADMINISTER to
5508 PRINTER_ACCESS_ADMINISTER for this to work. Something
5509 to do with the child (job) object becoming like a
5510 printer?? -tpot */
5512 access_type = PRINTER_ACCESS_ADMINISTER;
5515 /* Check access */
5517 map_printer_permissions(secdesc->sec);
5519 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5520 &access_granted, &status);
5522 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5524 /* see if we need to try the printer admin list */
5526 if ( access_granted == 0 ) {
5527 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5528 return True;
5531 talloc_destroy(mem_ctx);
5533 if (!result)
5534 errno = EACCES;
5536 return result;
5539 /****************************************************************************
5540 Check the time parameters allow a print operation.
5541 *****************************************************************************/
5543 BOOL print_time_access_check(int snum)
5545 NT_PRINTER_INFO_LEVEL *printer = NULL;
5546 BOOL ok = False;
5547 time_t now = time(NULL);
5548 struct tm *t;
5549 uint32 mins;
5551 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5552 return False;
5554 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5555 ok = True;
5557 t = gmtime(&now);
5558 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5560 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5561 ok = True;
5563 free_a_printer(&printer, 2);
5565 if (!ok)
5566 errno = EACCES;
5568 return ok;
5571 /****************************************************************************
5572 Fill in the servername sent in the _spoolss_open_printer_ex() call
5573 ****************************************************************************/
5575 char* get_server_name( Printer_entry *printer )
5577 return printer->servername;