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 3 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, see <http://www.gnu.org/licenses/>.
24 extern struct current_user current_user;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43 /* Map generic permissions to printer object specific permissions */
45 const struct generic_mapping printer_generic_mapping = {
52 const struct standard_mapping printer_std_mapping = {
59 /* Map generic permissions to print server object specific permissions */
61 const struct generic_mapping printserver_generic_mapping = {
68 const struct generic_mapping printserver_std_mapping = {
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static const nt_forms_struct default_forms[] = {
80 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 const char *long_archi;
202 const char *short_archi;
206 #define SPL_ARCH_WIN40 "WIN40"
207 #define SPL_ARCH_W32X86 "W32X86"
208 #define SPL_ARCH_W32MIPS "W32MIPS"
209 #define SPL_ARCH_W32ALPHA "W32ALPHA"
210 #define SPL_ARCH_W32PPC "W32PPC"
211 #define SPL_ARCH_IA64 "IA64"
212 #define SPL_ARCH_X64 "x64"
214 static const struct table_node archi_table[]= {
216 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
217 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
218 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
219 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
220 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
221 {"Windows IA64", SPL_ARCH_IA64, 3 },
222 {"Windows x64", SPL_ARCH_X64, 3 },
227 /****************************************************************************
228 generate a new TDB_DATA key for storing a printer
229 ****************************************************************************/
231 static TDB_DATA make_printer_tdbkey( const char *sharename )
234 static pstring keystr;
237 fstrcpy( share, sharename );
240 pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
242 key = string_term_tdb_data(keystr);
247 /****************************************************************************
248 generate a new TDB_DATA key for storing a printer security descriptor
249 ****************************************************************************/
251 static TDB_DATA make_printers_secdesc_tdbkey( const char* sharename )
254 static pstring keystr;
257 fstrcpy( share, sharename );
260 pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
262 key = string_term_tdb_data(keystr);
267 /****************************************************************************
268 ****************************************************************************/
270 static bool upgrade_to_version_3(void)
272 TDB_DATA kbuf, newkey, dbuf;
274 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
276 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
277 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
279 dbuf = tdb_fetch(tdb_drivers, kbuf);
281 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
282 DEBUG(0,("upgrade_to_version_3:moving form\n"));
283 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
284 SAFE_FREE(dbuf.dptr);
285 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
288 if (tdb_delete(tdb_drivers, kbuf) != 0) {
289 SAFE_FREE(dbuf.dptr);
290 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
295 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
296 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
297 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
298 SAFE_FREE(dbuf.dptr);
299 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
302 if (tdb_delete(tdb_drivers, kbuf) != 0) {
303 SAFE_FREE(dbuf.dptr);
304 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
309 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
310 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
311 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
312 SAFE_FREE(dbuf.dptr);
313 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
316 if (tdb_delete(tdb_drivers, kbuf) != 0) {
317 SAFE_FREE(dbuf.dptr);
318 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
323 SAFE_FREE(dbuf.dptr);
329 /*******************************************************************
330 Fix an issue with security descriptors. Printer sec_desc must
331 use more than the generic bits that were previously used
332 in <= 3.0.14a. They must also have a owner and group SID assigned.
333 Otherwise, any printers than have been migrated to a Windows
334 host using printmig.exe will not be accessible.
335 *******************************************************************/
337 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
338 TDB_DATA data, void *state )
341 SEC_DESC_BUF *sd_orig = NULL;
342 SEC_DESC_BUF *sd_new, *sd_store;
343 SEC_DESC *sec, *new_sec;
344 TALLOC_CTX *ctx = state;
350 if (!data.dptr || data.dsize == 0) {
354 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
358 /* upgrade the security descriptor */
362 prs_init( &ps, 0, ctx, UNMARSHALL );
363 prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
365 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
366 /* delete bad entries */
367 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
368 (const char *)key.dptr ));
369 tdb_delete( tdb_printers, key );
380 /* is this even valid? */
387 /* update access masks */
389 for ( i=0; i<sec->dacl->num_aces; i++ ) {
390 switch ( sec->dacl->aces[i].access_mask ) {
391 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
392 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
395 case GENERIC_ALL_ACCESS:
396 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
399 case READ_CONTROL_ACCESS:
400 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
402 default: /* no change */
407 /* create a new SEC_DESC with the appropriate owner and group SIDs */
409 string_to_sid(&sid, "S-1-5-32-544" );
410 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
412 NULL, NULL, &size_new_sec );
417 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
423 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
424 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
433 sd_size = sec_desc_size(sd_store->sd) + sizeof(SEC_DESC_BUF);
434 prs_init(&ps, sd_size, ctx, MARSHALL);
436 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
437 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
442 data.dptr = (uint8 *)prs_data_p( &ps );
443 data.dsize = sd_size;
445 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
449 /* 0 to continue and non-zero to stop traversal */
451 return (result == -1);
454 /*******************************************************************
455 *******************************************************************/
457 static bool upgrade_to_version_4(void)
462 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
464 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
467 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
469 talloc_destroy( ctx );
471 return ( result != -1 );
474 /*******************************************************************
475 Fix an issue with security descriptors. Printer sec_desc must
476 use more than the generic bits that were previously used
477 in <= 3.0.14a. They must also have a owner and group SID assigned.
478 Otherwise, any printers than have been migrated to a Windows
479 host using printmig.exe will not be accessible.
480 *******************************************************************/
482 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
483 TDB_DATA data, void *state )
487 if (!data.dptr || data.dsize == 0)
490 /* upgrade printer records and security descriptors */
492 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
493 new_key = make_printer_tdbkey( (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
495 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
496 new_key = make_printers_secdesc_tdbkey( (const char *)key.dptr+strlen(SECDESC_PREFIX) );
499 /* ignore this record */
503 /* delete the original record and store under the normalized key */
505 if ( tdb_delete( the_tdb, key ) != 0 ) {
506 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
511 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
512 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
520 /*******************************************************************
521 *******************************************************************/
523 static bool upgrade_to_version_5(void)
528 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
530 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
533 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
535 talloc_destroy( ctx );
537 return ( result != -1 );
540 /****************************************************************************
541 Open the NT printing tdbs. Done once before fork().
542 ****************************************************************************/
544 bool nt_printing_init(struct messaging_context *msg_ctx)
546 const char *vstring = "INFO/version";
550 if ( tdb_drivers && tdb_printers && tdb_forms )
554 tdb_close(tdb_drivers);
555 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
557 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
558 state_path("ntdrivers.tdb"), strerror(errno) ));
563 tdb_close(tdb_printers);
564 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
566 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
567 state_path("ntprinters.tdb"), strerror(errno) ));
572 tdb_close(tdb_forms);
573 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
575 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
576 state_path("ntforms.tdb"), strerror(errno) ));
580 /* handle a Samba upgrade */
582 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
584 DEBUG(10, ("Fresh database\n"));
585 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
586 vers_id = NTDRIVERS_DATABASE_VERSION_5;
589 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
591 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
592 if (!upgrade_to_version_3())
594 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
595 vers_id = NTDRIVERS_DATABASE_VERSION_3;
598 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
599 /* Written on a bigendian machine with old fetch_int code. Save as le. */
600 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
601 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
602 vers_id = NTDRIVERS_DATABASE_VERSION_3;
605 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
606 if ( !upgrade_to_version_4() )
608 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
609 vers_id = NTDRIVERS_DATABASE_VERSION_4;
612 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
613 if ( !upgrade_to_version_5() )
615 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
616 vers_id = NTDRIVERS_DATABASE_VERSION_5;
620 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
621 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
626 update_c_setprinter(True);
629 * register callback to handle updating printers as new
630 * drivers are installed
633 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
634 do_drv_upgrade_printer);
637 * register callback to handle updating printer data
638 * when a driver is initialized
641 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
642 reset_all_printerdata);
644 /* of course, none of the message callbacks matter if you don't
645 tell messages.c that you interested in receiving PRINT_GENERAL
646 msgs. This is done in claim_connection() */
649 if ( lp_security() == SEC_ADS ) {
650 win_rc = check_published_printers();
651 if (!W_ERROR_IS_OK(win_rc))
652 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
658 /*******************************************************************
659 Function to allow filename parsing "the old way".
660 ********************************************************************/
662 static void driver_unix_convert(connection_struct *conn,
664 SMB_STRUCT_STAT *pst)
666 char *new_name = NULL;
668 unix_clean_name(name);
669 trim_string(name,"/","/");
670 unix_convert(talloc_tos(),conn, name, False, &new_name, NULL, pst);
672 pstrcpy(name, new_name);
676 /*******************************************************************
677 tdb traversal function for counting printers.
678 ********************************************************************/
680 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
681 TDB_DATA data, void *context)
683 int *printer_count = (int*)context;
685 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
687 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
693 /*******************************************************************
694 Update the spooler global c_setprinter. This variable is initialized
695 when the parent smbd starts with the number of existing printers. It
696 is monotonically increased by the current number of printers *after*
697 each add or delete printer RPC. Only Microsoft knows why... JRR020119
698 ********************************************************************/
700 uint32 update_c_setprinter(bool initialize)
703 int32 printer_count = 0;
705 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
707 /* Traverse the tdb, counting the printers */
708 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
710 /* If initializing, set c_setprinter to current printers count
711 * otherwise, bump it by the current printer count
714 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
716 c_setprinter = printer_count;
718 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
719 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
721 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
723 return (uint32)c_setprinter;
726 /*******************************************************************
727 Get the spooler global c_setprinter, accounting for initialization.
728 ********************************************************************/
730 uint32 get_c_setprinter(void)
732 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
734 if (c_setprinter == (int32)-1)
735 c_setprinter = update_c_setprinter(True);
737 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
739 return (uint32)c_setprinter;
742 /****************************************************************************
743 Get builtin form struct list.
744 ****************************************************************************/
746 int get_builtin_ntforms(nt_forms_struct **list)
748 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
752 return sizeof(default_forms) / sizeof(default_forms[0]);
755 /****************************************************************************
756 get a builtin form struct
757 ****************************************************************************/
759 bool get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
763 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
764 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
765 count = sizeof(default_forms) / sizeof(default_forms[0]);
766 for (i=0;i<count;i++) {
767 if (strequal(form_name,default_forms[i].name)) {
768 DEBUGADD(6,("Found builtin form %s \n", form_name));
769 memcpy(form,&default_forms[i],sizeof(*form));
777 /****************************************************************************
778 get a form struct list.
779 ****************************************************************************/
781 int get_ntforms(nt_forms_struct **list)
783 TDB_DATA kbuf, newkey, dbuf;
784 nt_forms_struct form;
791 for (kbuf = tdb_firstkey(tdb_forms);
793 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
795 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
798 dbuf = tdb_fetch(tdb_forms, kbuf);
802 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
803 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
804 &i, &form.flag, &form.width, &form.length, &form.left,
805 &form.top, &form.right, &form.bottom);
806 SAFE_FREE(dbuf.dptr);
807 if (ret != dbuf.dsize)
810 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
812 DEBUG(0,("get_ntforms: Realloc fail.\n"));
823 /****************************************************************************
824 write a form struct list
825 ****************************************************************************/
826 int write_ntforms(nt_forms_struct **list, int number)
833 for (i=0;i<number;i++) {
834 /* save index, so list is rebuilt in correct order */
835 len = tdb_pack((uint8 *)buf, sizeof(buf), "dddddddd",
836 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
837 (*list)[i].left, (*list)[i].top, (*list)[i].right,
839 if (len > sizeof(buf)) break;
840 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
842 dbuf.dptr = (uint8 *)buf;
843 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) break;
849 /****************************************************************************
850 add a form struct at the end of the list
851 ****************************************************************************/
852 bool add_a_form(nt_forms_struct **list, const FORM *form, int *count)
859 * NT tries to add forms even when
860 * they are already in the base
861 * only update the values if already present
866 unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
867 for (n=0; n<*count; n++) {
868 if ( strequal((*list)[n].name, form_name) ) {
875 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
876 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
879 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
883 (*list)[n].flag=form->flags;
884 (*list)[n].width=form->size_x;
885 (*list)[n].length=form->size_y;
886 (*list)[n].left=form->left;
887 (*list)[n].top=form->top;
888 (*list)[n].right=form->right;
889 (*list)[n].bottom=form->bottom;
891 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
892 update ? "updated" : "added", form_name));
897 /****************************************************************************
898 Delete a named form struct.
899 ****************************************************************************/
901 bool delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
909 unistr2_to_ascii(form_name, del_name, sizeof(form_name));
911 for (n=0; n<*count; n++) {
912 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
913 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
919 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
920 *ret = WERR_INVALID_PARAM;
924 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
925 if (tdb_delete_bystring(tdb_forms, key) != 0) {
933 /****************************************************************************
934 Update a form struct.
935 ****************************************************************************/
937 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
941 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
943 DEBUG(106, ("[%s]\n", form_name));
944 for (n=0; n<count; n++) {
945 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
946 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
950 if (n==count) return;
952 (*list)[n].flag=form->flags;
953 (*list)[n].width=form->size_x;
954 (*list)[n].length=form->size_y;
955 (*list)[n].left=form->left;
956 (*list)[n].top=form->top;
957 (*list)[n].right=form->right;
958 (*list)[n].bottom=form->bottom;
961 /****************************************************************************
962 Get the nt drivers list.
963 Traverse the database and look-up the matching names.
964 ****************************************************************************/
965 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
968 const char *short_archi;
970 TDB_DATA kbuf, newkey;
972 short_archi = get_short_archi(architecture);
977 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
979 for (kbuf = tdb_firstkey(tdb_drivers);
981 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
983 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
986 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
987 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
991 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
998 /****************************************************************************
999 Function to do the mapping between the long architecture name and
1001 ****************************************************************************/
1003 const char *get_short_archi(const char *long_archi)
1007 DEBUG(107,("Getting architecture dependant directory\n"));
1010 } while ( (archi_table[i].long_archi!=NULL ) &&
1011 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1013 if (archi_table[i].long_archi==NULL) {
1014 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1018 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1020 DEBUGADD(108,("index: [%d]\n", i));
1021 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1022 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1024 return archi_table[i].short_archi;
1027 /****************************************************************************
1028 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1029 There are two case to be covered here: PE (Portable Executable) and NE (New
1030 Executable) files. Both files support the same INFO structure, but PE files
1031 store the signature in unicode, and NE files store it as !unicode.
1032 returns -1 on error, 1 on version info found, and 0 on no version info found.
1033 ****************************************************************************/
1035 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1041 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1042 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1043 fname, DOS_HEADER_SIZE));
1047 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1048 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1049 fname, (unsigned long)byte_count));
1050 goto no_version_info;
1053 /* Is this really a DOS header? */
1054 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1055 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1056 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1057 goto no_version_info;
1060 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1061 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1062 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1064 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1065 goto no_version_info;
1068 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1069 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1070 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1071 fname, (unsigned long)byte_count));
1072 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1073 goto no_version_info;
1076 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1077 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1078 unsigned int num_sections;
1079 unsigned int section_table_bytes;
1081 /* Just skip over optional header to get to section table */
1082 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
1083 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1084 SEEK_CUR) == (SMB_OFF_T)-1) {
1085 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1090 /* get the section table */
1091 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1092 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1093 if (section_table_bytes == 0)
1097 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1098 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1099 fname, section_table_bytes));
1103 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1104 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1105 fname, (unsigned long)byte_count));
1109 /* Iterate the section table looking for the resource section ".rsrc" */
1110 for (i = 0; i < num_sections; i++) {
1111 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1113 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1114 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1115 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1117 if (section_bytes == 0)
1121 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1122 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1123 fname, section_bytes));
1127 /* Seek to the start of the .rsrc section info */
1128 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1129 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1134 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1135 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1136 fname, (unsigned long)byte_count));
1140 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1143 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1144 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1145 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1146 /* Align to next long address */
1147 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1149 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1150 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1151 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1153 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1154 fname, *major, *minor,
1155 (*major>>16)&0xffff, *major&0xffff,
1156 (*minor>>16)&0xffff, *minor&0xffff));
1165 /* Version info not found, fall back to origin date/time */
1166 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1170 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1171 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1172 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1173 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1174 /* At this point, we assume the file is in error. It still could be somthing
1175 * else besides a NE file, but it unlikely at this point. */
1179 /* Allocate a bit more space to speed up things */
1181 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1182 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1183 fname, PE_HEADER_SIZE));
1187 /* This is a HACK! I got tired of trying to sort through the messy
1188 * 'NE' file format. If anyone wants to clean this up please have at
1189 * it, but this works. 'NE' files will eventually fade away. JRR */
1190 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1191 /* Cover case that should not occur in a well formed 'NE' .dll file */
1192 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1194 for(i=0; i<byte_count; i++) {
1195 /* Fast skip past data that can't possibly match */
1196 if (buf[i] != 'V') continue;
1198 /* Potential match data crosses buf boundry, move it to beginning
1199 * of buf, and fill the buf with as much as it will hold. */
1200 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1203 memcpy(buf, &buf[i], byte_count-i);
1204 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1205 (byte_count-i))) < 0) {
1207 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1212 byte_count = bc + (byte_count - i);
1213 if (byte_count<VS_VERSION_INFO_SIZE) break;
1218 /* Check that the full signature string and the magic number that
1219 * follows exist (not a perfect solution, but the chances that this
1220 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1221 * twice, as it is simpler to read the code. */
1222 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1223 /* Compute skip alignment to next long address */
1224 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1225 sizeof(VS_SIGNATURE)) & 3;
1226 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1228 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1229 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1230 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1231 fname, *major, *minor,
1232 (*major>>16)&0xffff, *major&0xffff,
1233 (*minor>>16)&0xffff, *minor&0xffff));
1240 /* Version info not found, fall back to origin date/time */
1241 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1246 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1247 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1248 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1259 /****************************************************************************
1260 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1261 share one or more files. During the MS installation process files are checked
1262 to insure that only a newer version of a shared file is installed over an
1263 older version. There are several possibilities for this comparison. If there
1264 is no previous version, the new one is newer (obviously). If either file is
1265 missing the version info structure, compare the creation date (on Unix use
1266 the modification date). Otherwise chose the numerically larger version number.
1267 ****************************************************************************/
1269 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1271 bool use_version = True;
1276 time_t new_create_time;
1280 time_t old_create_time;
1282 files_struct *fsp = NULL;
1284 SMB_STRUCT_STAT stat_buf;
1288 SET_STAT_INVALID(st);
1289 SET_STAT_INVALID(stat_buf);
1290 new_create_time = (time_t)0;
1291 old_create_time = (time_t)0;
1293 /* Get file version info (if available) for previous file (if it exists) */
1294 pstrcpy(filepath, old_file);
1296 driver_unix_convert(conn,filepath,&stat_buf);
1298 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1300 FILE_SHARE_READ|FILE_SHARE_WRITE,
1303 FILE_ATTRIBUTE_NORMAL,
1307 if (!NT_STATUS_IS_OK(status)) {
1308 /* Old file not found, so by definition new file is in fact newer */
1309 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1314 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1320 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1322 use_version = False;
1323 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1324 old_create_time = st.st_mtime;
1325 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1328 close_file(fsp, NORMAL_CLOSE);
1330 /* Get file version info (if available) for new file */
1331 pstrcpy(filepath, new_file);
1332 driver_unix_convert(conn,filepath,&stat_buf);
1334 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1336 FILE_SHARE_READ|FILE_SHARE_WRITE,
1339 FILE_ATTRIBUTE_NORMAL,
1343 if (!NT_STATUS_IS_OK(status)) {
1344 /* New file not found, this shouldn't occur if the caller did its job */
1345 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1350 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1356 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1358 use_version = False;
1359 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1360 new_create_time = st.st_mtime;
1361 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1364 close_file(fsp, NORMAL_CLOSE);
1366 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1367 /* Compare versions and choose the larger version number */
1368 if (new_major > old_major ||
1369 (new_major == old_major && new_minor > old_minor)) {
1371 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1375 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1380 /* Compare modification time/dates and choose the newest time/date */
1381 if (new_create_time > old_create_time) {
1382 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1386 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1393 close_file(fsp, NORMAL_CLOSE);
1397 /****************************************************************************
1398 Determine the correct cVersion associated with an architecture and driver
1399 ****************************************************************************/
1400 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1401 struct current_user *user, WERROR *perr)
1408 files_struct *fsp = NULL;
1410 connection_struct *conn;
1413 SET_STAT_INVALID(st);
1415 *perr = WERR_INVALID_PARAM;
1417 /* If architecture is Windows 95/98/ME, the version is always 0. */
1418 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1419 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1424 /* If architecture is Windows x64, the version is always 3. */
1425 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1426 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1432 * Connect to the print$ share under the same account as the user connected
1433 * to the rpc pipe. Note we must still be root to do this.
1436 /* Null password is ok - we are already an authenticated user... */
1437 null_pw = data_blob_null;
1438 fstrcpy(res_type, "A:");
1440 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1444 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1445 *perr = ntstatus_to_werror(nt_status);
1449 /* We are temporarily becoming the connection user. */
1450 if (!become_user(conn, user->vuid)) {
1451 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1452 *perr = WERR_ACCESS_DENIED;
1456 /* Open the driver file (Portable Executable format) and determine the
1457 * deriver the cversion. */
1458 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1460 driver_unix_convert(conn,driverpath,&st);
1462 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1463 *perr = WERR_BADFILE;
1467 status = open_file_ntcreate(conn, NULL, driverpath, &st,
1469 FILE_SHARE_READ|FILE_SHARE_WRITE,
1472 FILE_ATTRIBUTE_NORMAL,
1476 if (!NT_STATUS_IS_OK(status)) {
1477 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1478 driverpath, errno));
1479 *perr = WERR_ACCESS_DENIED;
1484 int ret = get_file_version(fsp, driverpath, &major, &minor);
1485 if (ret == -1) goto error_exit;
1488 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1493 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1494 * for more details. Version in this case is not just the version of the
1495 * file, but the version in the sense of kernal mode (2) vs. user mode
1496 * (3) drivers. Other bits of the version fields are the version info.
1499 cversion = major & 0x0000ffff;
1501 case 2: /* WinNT drivers */
1502 case 3: /* Win2K drivers */
1506 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1507 driverpath, cversion));
1511 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1512 driverpath, major, minor));
1515 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1516 driverpath, cversion));
1518 close_file(fsp, NORMAL_CLOSE);
1519 close_cnum(conn, user->vuid);
1528 close_file(fsp, NORMAL_CLOSE);
1530 close_cnum(conn, user->vuid);
1535 /****************************************************************************
1536 ****************************************************************************/
1537 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1538 struct current_user *user)
1540 const char *architecture;
1546 /* clean up the driver name.
1547 * we can get .\driver.dll
1548 * or worse c:\windows\system\driver.dll !
1550 /* using an intermediate string to not have overlaping memcpy()'s */
1551 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1552 fstrcpy(new_name, p+1);
1553 fstrcpy(driver->driverpath, new_name);
1556 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1557 fstrcpy(new_name, p+1);
1558 fstrcpy(driver->datafile, new_name);
1561 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1562 fstrcpy(new_name, p+1);
1563 fstrcpy(driver->configfile, new_name);
1566 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1567 fstrcpy(new_name, p+1);
1568 fstrcpy(driver->helpfile, new_name);
1571 if (driver->dependentfiles) {
1572 for (i=0; *driver->dependentfiles[i]; i++) {
1573 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1574 fstrcpy(new_name, p+1);
1575 fstrcpy(driver->dependentfiles[i], new_name);
1580 architecture = get_short_archi(driver->environment);
1581 if (!architecture) {
1582 return WERR_UNKNOWN_PRINTER_DRIVER;
1585 /* jfm:7/16/2000 the client always sends the cversion=0.
1586 * The server should check which version the driver is by reading
1587 * the PE header of driver->driverpath.
1589 * For Windows 95/98 the version is 0 (so the value sent is correct)
1590 * For Windows NT (the architecture doesn't matter)
1591 * NT 3.1: cversion=0
1592 * NT 3.5/3.51: cversion=1
1596 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1602 /****************************************************************************
1603 ****************************************************************************/
1604 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1606 const char *architecture;
1612 /* clean up the driver name.
1613 * we can get .\driver.dll
1614 * or worse c:\windows\system\driver.dll !
1616 /* using an intermediate string to not have overlaping memcpy()'s */
1617 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1618 fstrcpy(new_name, p+1);
1619 fstrcpy(driver->driverpath, new_name);
1622 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1623 fstrcpy(new_name, p+1);
1624 fstrcpy(driver->datafile, new_name);
1627 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1628 fstrcpy(new_name, p+1);
1629 fstrcpy(driver->configfile, new_name);
1632 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1633 fstrcpy(new_name, p+1);
1634 fstrcpy(driver->helpfile, new_name);
1637 if (driver->dependentfiles) {
1638 for (i=0; *driver->dependentfiles[i]; i++) {
1639 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1640 fstrcpy(new_name, p+1);
1641 fstrcpy(driver->dependentfiles[i], new_name);
1646 architecture = get_short_archi(driver->environment);
1647 if (!architecture) {
1648 return WERR_UNKNOWN_PRINTER_DRIVER;
1651 /* jfm:7/16/2000 the client always sends the cversion=0.
1652 * The server should check which version the driver is by reading
1653 * the PE header of driver->driverpath.
1655 * For Windows 95/98 the version is 0 (so the value sent is correct)
1656 * For Windows NT (the architecture doesn't matter)
1657 * NT 3.1: cversion=0
1658 * NT 3.5/3.51: cversion=1
1663 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1669 /****************************************************************************
1670 ****************************************************************************/
1671 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1672 uint32 level, struct current_user *user)
1677 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1678 driver=driver_abstract.info_3;
1679 return clean_up_driver_struct_level_3(driver, user);
1683 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1684 driver=driver_abstract.info_6;
1685 return clean_up_driver_struct_level_6(driver, user);
1688 return WERR_INVALID_PARAM;
1692 /****************************************************************************
1693 This function sucks and should be replaced. JRA.
1694 ****************************************************************************/
1696 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1698 dst->cversion = src->version;
1700 fstrcpy( dst->name, src->name);
1701 fstrcpy( dst->environment, src->environment);
1702 fstrcpy( dst->driverpath, src->driverpath);
1703 fstrcpy( dst->datafile, src->datafile);
1704 fstrcpy( dst->configfile, src->configfile);
1705 fstrcpy( dst->helpfile, src->helpfile);
1706 fstrcpy( dst->monitorname, src->monitorname);
1707 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1708 dst->dependentfiles = src->dependentfiles;
1711 #if 0 /* Debugging function */
1713 static char* ffmt(unsigned char *c){
1715 static char ffmt_str[17];
1717 for (i=0; i<16; i++) {
1718 if ((c[i] < ' ') || (c[i] > '~'))
1729 /****************************************************************************
1730 ****************************************************************************/
1731 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1732 struct current_user *user, WERROR *perr)
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1735 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1736 const char *architecture;
1741 connection_struct *conn;
1749 TALLOC_CTX *ctx = talloc_tos();
1751 memset(inbuf, '\0', sizeof(inbuf));
1752 memset(outbuf, '\0', sizeof(outbuf));
1756 driver=driver_abstract.info_3;
1757 else if (level==6) {
1758 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1759 driver = &converted_driver;
1761 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1762 return WERR_UNKNOWN_LEVEL;
1765 architecture = get_short_archi(driver->environment);
1766 if (!architecture) {
1767 return WERR_UNKNOWN_PRINTER_DRIVER;
1771 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1772 * Note we must be root to do this.
1775 null_pw = data_blob_null;
1776 fstrcpy(res_type, "A:");
1778 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1782 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1783 *perr = ntstatus_to_werror(nt_status);
1784 return WERR_NO_SUCH_SHARE;
1788 * Save who we are - we are temporarily becoming the connection user.
1791 if (!become_user(conn, conn->vuid)) {
1792 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1793 return WERR_ACCESS_DENIED;
1797 * make the directories version and version\driver_name
1798 * under the architecture directory.
1800 DEBUG(5,("Creating first directory\n"));
1801 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1802 driver_unix_convert(conn,new_dir,&st);
1803 create_directory(conn, new_dir);
1805 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1806 * listed for this driver which has already been moved, skip it (note:
1807 * drivers may list the same file name several times. Then check if the
1808 * file already exists in archi\cversion\, if so, check that the version
1809 * info (or time stamps if version info is unavailable) is newer (or the
1810 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1811 * Otherwise, delete the file.
1813 * If a file is not moved to archi\cversion\ because of an error, all the
1814 * rest of the 'unmoved' driver files are removed from archi\. If one or
1815 * more of the driver's files was already moved to archi\cversion\, it
1816 * potentially leaves the driver in a partially updated state. Version
1817 * trauma will most likely occur if an client attempts to use any printer
1818 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1819 * done is appropriate... later JRR
1822 DEBUG(5,("Moving files now !\n"));
1824 if (driver->driverpath && strlen(driver->driverpath)) {
1825 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1826 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1827 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1828 driver_unix_convert(conn,new_name,&st);
1829 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1830 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1831 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1832 new_name, old_name));
1833 *perr = WERR_ACCESS_DENIED;
1839 if (driver->datafile && strlen(driver->datafile)) {
1840 if (!strequal(driver->datafile, driver->driverpath)) {
1841 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1842 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1843 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1844 driver_unix_convert(conn,new_name,&st);
1845 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1846 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1847 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1848 new_name, old_name));
1849 *perr = WERR_ACCESS_DENIED;
1856 if (driver->configfile && strlen(driver->configfile)) {
1857 if (!strequal(driver->configfile, driver->driverpath) &&
1858 !strequal(driver->configfile, driver->datafile)) {
1859 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1860 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1861 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1862 driver_unix_convert(conn,new_name,&st);
1863 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1864 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1865 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1866 new_name, old_name));
1867 *perr = WERR_ACCESS_DENIED;
1874 if (driver->helpfile && strlen(driver->helpfile)) {
1875 if (!strequal(driver->helpfile, driver->driverpath) &&
1876 !strequal(driver->helpfile, driver->datafile) &&
1877 !strequal(driver->helpfile, driver->configfile)) {
1878 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1879 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1880 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1881 driver_unix_convert(conn,new_name,&st);
1882 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1883 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1884 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1885 new_name, old_name));
1886 *perr = WERR_ACCESS_DENIED;
1893 if (driver->dependentfiles) {
1894 for (i=0; *driver->dependentfiles[i]; i++) {
1895 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1896 !strequal(driver->dependentfiles[i], driver->datafile) &&
1897 !strequal(driver->dependentfiles[i], driver->configfile) &&
1898 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1900 for (j=0; j < i; j++) {
1901 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1906 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1907 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1908 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1909 driver_unix_convert(conn,new_name,&st);
1910 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
1911 OPENX_FILE_EXISTS_TRUNCATE|
1912 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1913 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1914 new_name, old_name));
1915 *perr = WERR_ACCESS_DENIED;
1924 close_cnum(conn, user->vuid);
1927 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1930 /****************************************************************************
1931 ****************************************************************************/
1932 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1935 const char *architecture;
1943 architecture = get_short_archi(driver->environment);
1944 if (!architecture) {
1948 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1949 * \\server is added in the rpc server layer.
1950 * It does make sense to NOT store the server's name in the printer TDB.
1953 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1955 /* .inf files do not always list a file for each of the four standard files.
1956 * Don't prepend a path to a null filename, or client claims:
1957 * "The server on which the printer resides does not have a suitable
1958 * <printer driver name> printer driver installed. Click OK if you
1959 * wish to install the driver on your local machine."
1961 if (strlen(driver->driverpath)) {
1962 fstrcpy(temp_name, driver->driverpath);
1963 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1966 if (strlen(driver->datafile)) {
1967 fstrcpy(temp_name, driver->datafile);
1968 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1971 if (strlen(driver->configfile)) {
1972 fstrcpy(temp_name, driver->configfile);
1973 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1976 if (strlen(driver->helpfile)) {
1977 fstrcpy(temp_name, driver->helpfile);
1978 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1981 if (driver->dependentfiles) {
1982 for (i=0; *driver->dependentfiles[i]; i++) {
1983 fstrcpy(temp_name, driver->dependentfiles[i]);
1984 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1988 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1990 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1997 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2000 driver->environment,
2005 driver->monitorname,
2006 driver->defaultdatatype);
2008 if (driver->dependentfiles) {
2009 for (i=0; *driver->dependentfiles[i]; i++) {
2010 len += tdb_pack(buf+len, buflen-len, "f",
2011 driver->dependentfiles[i]);
2015 if (len != buflen) {
2016 buf = (uint8 *)SMB_REALLOC(buf, len);
2018 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2029 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2033 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2039 /****************************************************************************
2040 ****************************************************************************/
2041 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2043 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2046 info3.cversion = driver->version;
2047 fstrcpy(info3.name,driver->name);
2048 fstrcpy(info3.environment,driver->environment);
2049 fstrcpy(info3.driverpath,driver->driverpath);
2050 fstrcpy(info3.datafile,driver->datafile);
2051 fstrcpy(info3.configfile,driver->configfile);
2052 fstrcpy(info3.helpfile,driver->helpfile);
2053 fstrcpy(info3.monitorname,driver->monitorname);
2054 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2055 info3.dependentfiles = driver->dependentfiles;
2057 return add_a_printer_driver_3(&info3);
2061 /****************************************************************************
2062 ****************************************************************************/
2063 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2065 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2069 fstrcpy(info.name, driver);
2070 fstrcpy(info.defaultdatatype, "RAW");
2072 fstrcpy(info.driverpath, "");
2073 fstrcpy(info.datafile, "");
2074 fstrcpy(info.configfile, "");
2075 fstrcpy(info.helpfile, "");
2077 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2080 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2081 fstrcpy(info.dependentfiles[0], "");
2083 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2085 SAFE_FREE(info.dependentfiles);
2092 /****************************************************************************
2093 ****************************************************************************/
2094 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2096 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2098 const char *architecture;
2103 ZERO_STRUCT(driver);
2105 architecture = get_short_archi(arch);
2106 if ( !architecture ) {
2107 return WERR_UNKNOWN_PRINTER_DRIVER;
2110 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2112 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2115 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2117 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2119 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2121 return WERR_UNKNOWN_PRINTER_DRIVER;
2123 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2132 driver.defaultdatatype);
2135 while (len < dbuf.dsize) {
2136 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2137 if ( !driver.dependentfiles ) {
2138 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2142 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2143 &driver.dependentfiles[i]);
2147 if ( driver.dependentfiles )
2148 fstrcpy( driver.dependentfiles[i], "" );
2150 SAFE_FREE(dbuf.dptr);
2152 if (len != dbuf.dsize) {
2153 SAFE_FREE(driver.dependentfiles);
2155 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2158 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2160 SAFE_FREE(driver.dependentfiles);
2167 /****************************************************************************
2168 Debugging function, dump at level 6 the struct in the logs.
2169 ****************************************************************************/
2171 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2174 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2177 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2183 if (driver.info_3 == NULL)
2186 info3=driver.info_3;
2188 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2189 DEBUGADD(20,("name:[%s]\n", info3->name));
2190 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2191 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2192 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2193 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2194 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2195 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2196 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2198 for (i=0; info3->dependentfiles &&
2199 *info3->dependentfiles[i]; i++) {
2200 DEBUGADD(20,("dependentfile:[%s]\n",
2201 info3->dependentfiles[i]));
2208 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2216 /****************************************************************************
2217 ****************************************************************************/
2218 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2222 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2227 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2228 nt_devmode->devicename,
2229 nt_devmode->formname,
2231 nt_devmode->specversion,
2232 nt_devmode->driverversion,
2234 nt_devmode->driverextra,
2235 nt_devmode->orientation,
2236 nt_devmode->papersize,
2237 nt_devmode->paperlength,
2238 nt_devmode->paperwidth,
2241 nt_devmode->defaultsource,
2242 nt_devmode->printquality,
2245 nt_devmode->yresolution,
2246 nt_devmode->ttoption,
2247 nt_devmode->collate,
2248 nt_devmode->logpixels,
2251 nt_devmode->bitsperpel,
2252 nt_devmode->pelswidth,
2253 nt_devmode->pelsheight,
2254 nt_devmode->displayflags,
2255 nt_devmode->displayfrequency,
2256 nt_devmode->icmmethod,
2257 nt_devmode->icmintent,
2258 nt_devmode->mediatype,
2259 nt_devmode->dithertype,
2260 nt_devmode->reserved1,
2261 nt_devmode->reserved2,
2262 nt_devmode->panningwidth,
2263 nt_devmode->panningheight,
2264 nt_devmode->nt_dev_private);
2267 if (nt_devmode->nt_dev_private) {
2268 len += tdb_pack(buf+len, buflen-len, "B",
2269 nt_devmode->driverextra,
2270 nt_devmode->nt_dev_private);
2273 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2278 /****************************************************************************
2279 Pack all values in all printer keys
2280 ***************************************************************************/
2282 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2286 REGISTRY_VALUE *val;
2287 REGVAL_CTR *val_ctr;
2294 /* loop over all keys */
2296 for ( i=0; i<data->num_keys; i++ ) {
2297 val_ctr = data->keys[i].values;
2298 num_values = regval_ctr_numvals( val_ctr );
2300 /* pack the keyname followed by a empty value */
2302 len += tdb_pack(buf+len, buflen-len, "pPdB",
2303 &data->keys[i].name,
2309 /* now loop over all values */
2311 for ( j=0; j<num_values; j++ ) {
2312 /* pathname should be stored as <key>\<value> */
2314 val = regval_ctr_specific_value( val_ctr, j );
2315 pstrcpy( path, data->keys[i].name );
2316 pstrcat( path, "\\" );
2317 pstrcat( path, regval_name(val) );
2319 len += tdb_pack(buf+len, buflen-len, "pPdB",
2324 regval_data_p(val) );
2326 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2333 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2339 /****************************************************************************
2340 Delete a printer - this just deletes the printer info file, any open
2341 handles are not affected.
2342 ****************************************************************************/
2344 uint32 del_a_printer(const char *sharename)
2347 pstring printdb_path;
2349 kbuf = make_printer_tdbkey( sharename );
2350 tdb_delete(tdb_printers, kbuf);
2352 kbuf= make_printers_secdesc_tdbkey( sharename );
2353 tdb_delete(tdb_printers, kbuf);
2355 close_all_print_db();
2357 if (geteuid() == 0) {
2358 pstrcpy(printdb_path, lock_path("printing/"));
2359 pstrcat(printdb_path, sharename);
2360 pstrcat(printdb_path, ".tdb");
2362 unlink(printdb_path);
2368 /****************************************************************************
2369 ****************************************************************************/
2370 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2375 TDB_DATA kbuf, dbuf;
2378 * in addprinter: no servername and the printer is the name
2379 * in setprinter: servername is \\server
2380 * and printer is \\server\\printer
2382 * Samba manages only local printers.
2383 * we currently don't support things like i
2384 * path=\\other_server\printer
2386 * We only store the printername, not \\server\printername
2389 if ( info->servername[0] != '\0' ) {
2390 trim_string(info->printername, info->servername, NULL);
2391 trim_char(info->printername, '\\', '\0');
2392 info->servername[0]='\0';
2396 * JFM: one day I'll forget.
2397 * below that's info->portname because that's the SAMBA sharename
2398 * and I made NT 'thinks' it's the portname
2399 * the info->sharename is the thing you can name when you add a printer
2400 * that's the short-name when you create shared printer for 95/98
2401 * So I've made a limitation in SAMBA: you can only have 1 printer model
2402 * behind a SAMBA share.
2410 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2413 info->default_priority,
2430 info->printprocessor,
2434 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2436 len += pack_values( info->data, buf+len, buflen-len );
2438 if (buflen != len) {
2439 buf = (uint8 *)SMB_REALLOC(buf, len);
2441 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2450 kbuf = make_printer_tdbkey( info->sharename );
2455 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2458 if (!W_ERROR_IS_OK(ret))
2459 DEBUG(8, ("error updating printer to tdb on disk\n"));
2463 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2464 info->sharename, info->drivername, info->portname, len));
2470 /****************************************************************************
2471 Malloc and return an NT devicemode.
2472 ****************************************************************************/
2474 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2477 char adevice[MAXDEVICENAME];
2478 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2480 if (nt_devmode == NULL) {
2481 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2485 ZERO_STRUCTP(nt_devmode);
2487 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2488 fstrcpy(nt_devmode->devicename, adevice);
2490 fstrcpy(nt_devmode->formname, "Letter");
2492 nt_devmode->specversion = 0x0401;
2493 nt_devmode->driverversion = 0x0400;
2494 nt_devmode->size = 0x00DC;
2495 nt_devmode->driverextra = 0x0000;
2496 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2497 DEFAULTSOURCE | COPIES | SCALE |
2498 PAPERSIZE | ORIENTATION;
2499 nt_devmode->orientation = 1;
2500 nt_devmode->papersize = PAPER_LETTER;
2501 nt_devmode->paperlength = 0;
2502 nt_devmode->paperwidth = 0;
2503 nt_devmode->scale = 0x64;
2504 nt_devmode->copies = 1;
2505 nt_devmode->defaultsource = BIN_FORMSOURCE;
2506 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2507 nt_devmode->color = COLOR_MONOCHROME;
2508 nt_devmode->duplex = DUP_SIMPLEX;
2509 nt_devmode->yresolution = 0;
2510 nt_devmode->ttoption = TT_SUBDEV;
2511 nt_devmode->collate = COLLATE_FALSE;
2512 nt_devmode->icmmethod = 0;
2513 nt_devmode->icmintent = 0;
2514 nt_devmode->mediatype = 0;
2515 nt_devmode->dithertype = 0;
2517 /* non utilisés par un driver d'imprimante */
2518 nt_devmode->logpixels = 0;
2519 nt_devmode->bitsperpel = 0;
2520 nt_devmode->pelswidth = 0;
2521 nt_devmode->pelsheight = 0;
2522 nt_devmode->displayflags = 0;
2523 nt_devmode->displayfrequency = 0;
2524 nt_devmode->reserved1 = 0;
2525 nt_devmode->reserved2 = 0;
2526 nt_devmode->panningwidth = 0;
2527 nt_devmode->panningheight = 0;
2529 nt_devmode->nt_dev_private = NULL;
2533 /****************************************************************************
2534 Deepcopy an NT devicemode.
2535 ****************************************************************************/
2537 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2539 NT_DEVICEMODE *new_nt_devicemode = NULL;
2541 if ( !nt_devicemode )
2544 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2545 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2549 new_nt_devicemode->nt_dev_private = NULL;
2550 if (nt_devicemode->nt_dev_private != NULL) {
2551 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2552 SAFE_FREE(new_nt_devicemode);
2553 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2558 return new_nt_devicemode;
2561 /****************************************************************************
2562 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2563 ****************************************************************************/
2565 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2567 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2569 if(nt_devmode == NULL)
2572 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2574 SAFE_FREE(nt_devmode->nt_dev_private);
2575 SAFE_FREE(*devmode_ptr);
2578 /****************************************************************************
2579 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2580 ****************************************************************************/
2582 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2584 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2589 free_nt_devicemode(&info->devmode);
2591 TALLOC_FREE( *info_ptr );
2595 /****************************************************************************
2596 ****************************************************************************/
2597 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2601 NT_DEVICEMODE devmode;
2603 ZERO_STRUCT(devmode);
2605 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2607 if (!*nt_devmode) return len;
2609 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2613 &devmode.specversion,
2614 &devmode.driverversion,
2616 &devmode.driverextra,
2617 &devmode.orientation,
2619 &devmode.paperlength,
2620 &devmode.paperwidth,
2623 &devmode.defaultsource,
2624 &devmode.printquality,
2627 &devmode.yresolution,
2633 &devmode.bitsperpel,
2635 &devmode.pelsheight,
2636 &devmode.displayflags,
2637 &devmode.displayfrequency,
2641 &devmode.dithertype,
2644 &devmode.panningwidth,
2645 &devmode.panningheight,
2646 &devmode.nt_dev_private);
2648 if (devmode.nt_dev_private) {
2649 /* the len in tdb_unpack is an int value and
2650 * devmode.driverextra is only a short
2652 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2653 devmode.driverextra=(uint16)extra_len;
2655 /* check to catch an invalid TDB entry so we don't segfault */
2656 if (devmode.driverextra == 0) {
2657 devmode.nt_dev_private = NULL;
2661 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2663 SAFE_FREE(devmode.nt_dev_private);
2667 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2668 if (devmode.nt_dev_private)
2669 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2674 /****************************************************************************
2675 Allocate and initialize a new slot.
2676 ***************************************************************************/
2678 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2683 if ( !name || !data )
2686 /* allocate another slot in the NT_PRINTER_KEY array */
2688 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2689 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2695 key_index = data->num_keys;
2697 /* initialze new key */
2699 data->keys[key_index].name = talloc_strdup( data, name );
2701 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2706 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2711 /****************************************************************************
2712 search for a registry key name in the existing printer data
2713 ***************************************************************************/
2715 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2719 for ( i=0; i<data->num_keys; i++ ) {
2720 if ( strequal( data->keys[i].name, name ) ) {
2722 /* cleanup memory */
2724 TALLOC_FREE( data->keys[i].name );
2725 TALLOC_FREE( data->keys[i].values );
2727 /* if not the end of the array, move remaining elements down one slot */
2730 if ( data->num_keys && (i < data->num_keys) )
2731 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2738 return data->num_keys;
2741 /****************************************************************************
2742 search for a registry key name in the existing printer data
2743 ***************************************************************************/
2745 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2750 if ( !data || !name )
2753 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2755 /* loop over all existing keys */
2757 for ( i=0; i<data->num_keys; i++ ) {
2758 if ( strequal(data->keys[i].name, name) ) {
2759 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2769 /****************************************************************************
2770 ***************************************************************************/
2772 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2776 int num_subkeys = 0;
2778 fstring *subkeys_ptr = NULL;
2789 /* special case of asking for the top level printer data registry key names */
2791 if ( strlen(key) == 0 ) {
2792 for ( i=0; i<data->num_keys; i++ ) {
2794 /* found a match, so allocate space and copy the name */
2796 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2797 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2802 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2809 /* asking for the subkeys of some key */
2810 /* subkey paths are stored in the key name using '\' as the delimiter */
2812 for ( i=0; i<data->num_keys; i++ ) {
2813 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2815 /* if we found the exact key, then break */
2816 key_len = strlen( key );
2817 if ( strlen(data->keys[i].name) == key_len )
2820 /* get subkey path */
2822 p = data->keys[i].name + key_len;
2825 fstrcpy( subkeyname, p );
2826 if ( (p = strchr( subkeyname, '\\' )) )
2829 /* don't add a key more than once */
2831 for ( j=0; j<num_subkeys; j++ ) {
2832 if ( strequal( subkeys_ptr[j], subkeyname ) )
2836 if ( j != num_subkeys )
2839 /* found a match, so allocate space and copy the name */
2841 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2842 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2847 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2853 /* return error if the key was not found */
2855 if ( i == data->num_keys ) {
2856 SAFE_FREE(subkeys_ptr);
2861 /* tag off the end */
2864 fstrcpy(subkeys_ptr[num_subkeys], "" );
2866 *subkeys = subkeys_ptr;
2872 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2875 smb_ucs2_t conv_str[1024];
2878 regval_ctr_delvalue(ctr, val_name);
2879 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2880 STR_TERMINATE | STR_NOALIGN);
2881 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2882 (char *) conv_str, str_size);
2885 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2888 regval_ctr_delvalue(ctr, val_name);
2889 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2890 (char *) &dword, sizeof(dword));
2893 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2896 uint8 bin_bool = (b ? 1 : 0);
2897 regval_ctr_delvalue(ctr, val_name);
2898 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2899 (char *) &bin_bool, sizeof(bin_bool));
2902 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2903 const char *multi_sz)
2905 smb_ucs2_t *conv_strs = NULL;
2908 /* a multi-sz has to have a null string terminator, i.e., the last
2909 string must be followed by two nulls */
2910 str_size = strlen(multi_sz) + 2;
2911 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2916 /* Change to byte units. */
2917 str_size *= sizeof(smb_ucs2_t);
2918 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2919 STR_TERMINATE | STR_NOALIGN);
2921 regval_ctr_delvalue(ctr, val_name);
2922 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2923 (char *) conv_strs, str_size);
2924 safe_free(conv_strs);
2928 /****************************************************************************
2929 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2931 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2932 * @return bool indicating success or failure
2933 ***************************************************************************/
2935 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2937 REGVAL_CTR *ctr = NULL;
2939 const char *dnssuffix;
2940 char *allocated_string = NULL;
2941 const char *ascii_str;
2944 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2945 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2946 ctr = info2->data->keys[i].values;
2948 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2949 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2951 /* we make the assumption that the netbios name is the same
2952 as the DNS name sinc ethe former will be what we used to
2955 dnssuffix = get_mydnsdomname(talloc_tos());
2956 if (dnssuffix && *dnssuffix) {
2957 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2959 fstrcpy( longname, global_myname() );
2962 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2964 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2965 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2966 SAFE_FREE(allocated_string);
2968 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2969 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2970 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2971 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2972 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2973 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2974 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2975 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2976 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2978 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2979 (info2->attributes &
2980 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2982 switch (info2->attributes & 0x3) {
2984 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2987 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2990 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2993 ascii_str = "unknown";
2995 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3000 /*****************************************************************
3001 ****************************************************************/
3003 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3007 REGVAL_CTR *ctr=NULL;
3008 UNISTR2 unistr_guid;
3010 /* find the DsSpooler key */
3011 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3012 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3013 ctr = info2->data->keys[i].values;
3015 regval_ctr_delvalue(ctr, "objectGUID");
3017 /* We used to store this as a REG_BINARY but that causes
3020 ZERO_STRUCT( unistr_guid );
3021 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3022 UNI_STR_TERMINATE );
3024 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3025 (char *)unistr_guid.buffer,
3026 unistr_guid.uni_max_len*2);
3030 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3031 NT_PRINTER_INFO_LEVEL *printer)
3035 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3036 char *srv_dn_utf8, **srv_cn_utf8;
3039 const char *attrs[] = {"objectGUID", NULL};
3041 WERROR win_rc = WERR_OK;
3043 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3045 /* figure out where to publish */
3046 ads_find_machine_acct(ads, &res, global_myname());
3048 /* We use ldap_get_dn here as we need the answer
3049 * in utf8 to call ldap_explode_dn(). JRA. */
3051 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3054 return WERR_SERVER_UNAVAILABLE;
3056 ads_msgfree(ads, res);
3057 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3059 ldap_memfree(srv_dn_utf8);
3061 return WERR_SERVER_UNAVAILABLE;
3063 /* Now convert to CH_UNIX. */
3064 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3065 ldap_memfree(srv_dn_utf8);
3066 ldap_memfree(srv_cn_utf8);
3068 return WERR_SERVER_UNAVAILABLE;
3070 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3071 ldap_memfree(srv_dn_utf8);
3072 ldap_memfree(srv_cn_utf8);
3075 return WERR_SERVER_UNAVAILABLE;
3078 ldap_memfree(srv_dn_utf8);
3079 ldap_memfree(srv_cn_utf8);
3081 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3082 if (!srv_cn_escaped) {
3083 SAFE_FREE(srv_cn_0);
3084 ldap_memfree(srv_dn_utf8);
3086 return WERR_SERVER_UNAVAILABLE;
3088 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3089 if (!sharename_escaped) {
3090 SAFE_FREE(srv_cn_escaped);
3091 SAFE_FREE(srv_cn_0);
3092 ldap_memfree(srv_dn_utf8);
3094 return WERR_SERVER_UNAVAILABLE;
3098 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3101 SAFE_FREE(srv_cn_0);
3102 SAFE_FREE(srv_cn_escaped);
3103 SAFE_FREE(sharename_escaped);
3105 /* build the ads mods */
3106 ctx = talloc_init("nt_printer_publish_ads");
3112 mods = ads_init_mods(ctx);
3116 talloc_destroy(ctx);
3120 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3121 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3122 printer->info_2->sharename);
3125 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3126 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3127 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3129 if (!ADS_ERR_OK(ads_rc))
3130 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3132 talloc_destroy(ctx);
3134 /* retreive the guid and store it locally */
3135 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3137 ads_pull_guid(ads, res, &guid);
3138 ads_msgfree(ads, res);
3139 store_printer_guid(printer->info_2, guid);
3140 win_rc = mod_a_printer(printer, 2);
3147 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3148 NT_PRINTER_INFO_LEVEL *printer)
3152 char *prt_dn = NULL;
3154 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3156 /* remove the printer from the directory */
3157 ads_rc = ads_find_printer_on_server(ads, &res,
3158 printer->info_2->sharename, global_myname());
3160 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3161 prt_dn = ads_get_dn(ads, res);
3163 ads_msgfree(ads, res);
3166 ads_rc = ads_del_dn(ads, prt_dn);
3167 ads_memfree(ads, prt_dn);
3170 ads_msgfree(ads, res);
3174 /****************************************************************************
3175 * Publish a printer in the directory
3177 * @param snum describing printer service
3178 * @return WERROR indicating status of publishing
3179 ***************************************************************************/
3181 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3184 ADS_STRUCT *ads = NULL;
3185 NT_PRINTER_INFO_LEVEL *printer = NULL;
3188 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3189 if (!W_ERROR_IS_OK(win_rc))
3193 case SPOOL_DS_PUBLISH:
3194 case SPOOL_DS_UPDATE:
3195 /* set the DsSpooler info and attributes */
3196 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3197 win_rc = WERR_NOMEM;
3201 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3203 case SPOOL_DS_UNPUBLISH:
3204 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3207 win_rc = WERR_NOT_SUPPORTED;
3211 win_rc = mod_a_printer(printer, 2);
3212 if (!W_ERROR_IS_OK(win_rc)) {
3213 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3217 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3219 DEBUG(3, ("ads_init() failed\n"));
3220 win_rc = WERR_SERVER_UNAVAILABLE;
3223 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3224 SAFE_FREE(ads->auth.password);
3225 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3228 /* ads_connect() will find the DC for us */
3229 ads_rc = ads_connect(ads);
3230 if (!ADS_ERR_OK(ads_rc)) {
3231 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3232 win_rc = WERR_ACCESS_DENIED;
3237 case SPOOL_DS_PUBLISH:
3238 case SPOOL_DS_UPDATE:
3239 win_rc = nt_printer_publish_ads(ads, printer);
3241 case SPOOL_DS_UNPUBLISH:
3242 win_rc = nt_printer_unpublish_ads(ads, printer);
3247 free_a_printer(&printer, 2);
3252 WERROR check_published_printers(void)
3255 ADS_STRUCT *ads = NULL;
3257 int n_services = lp_numservices();
3258 NT_PRINTER_INFO_LEVEL *printer = NULL;
3260 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3262 DEBUG(3, ("ads_init() failed\n"));
3263 return WERR_SERVER_UNAVAILABLE;
3265 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3266 SAFE_FREE(ads->auth.password);
3267 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3270 /* ads_connect() will find the DC for us */
3271 ads_rc = ads_connect(ads);
3272 if (!ADS_ERR_OK(ads_rc)) {
3273 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3275 ads_kdestroy("MEMORY:prtpub_cache");
3276 return WERR_ACCESS_DENIED;
3279 for (snum = 0; snum < n_services; snum++) {
3280 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3283 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3284 lp_servicename(snum))) &&
3285 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3286 nt_printer_publish_ads(ads, printer);
3288 free_a_printer(&printer, 2);
3292 ads_kdestroy("MEMORY:prtpub_cache");
3296 bool is_printer_published(Printer_entry *print_hnd, int snum,
3299 NT_PRINTER_INFO_LEVEL *printer = NULL;
3301 REGISTRY_VALUE *guid_val;
3306 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3308 if (!W_ERROR_IS_OK(win_rc) ||
3309 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3310 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3311 !(ctr = printer->info_2->data->keys[i].values) ||
3312 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3314 free_a_printer(&printer, 2);
3318 /* fetching printer guids really ought to be a separate function. */
3323 /* We used to store the guid as REG_BINARY, then swapped
3324 to REG_SZ for Vista compatibility so check for both */
3326 switch ( regval_type(guid_val) ){
3328 rpcstr_pull( guid_str, regval_data_p(guid_val),
3329 sizeof(guid_str)-1, -1, STR_TERMINATE );
3330 ret = smb_string_to_uuid( guid_str, guid );
3333 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3337 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3340 DEBUG(0,("is_printer_published: GUID value stored as "
3341 "invaluid type (%d)\n", regval_type(guid_val) ));
3346 free_a_printer(&printer, 2);
3350 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3355 WERROR check_published_printers(void)
3360 bool is_printer_published(Printer_entry *print_hnd, int snum,
3365 #endif /* HAVE_ADS */
3367 /****************************************************************************
3368 ***************************************************************************/
3370 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3372 NT_PRINTER_DATA *data;
3374 int removed_keys = 0;
3378 empty_slot = data->num_keys;
3381 return WERR_INVALID_PARAM;
3383 /* remove all keys */
3385 if ( !strlen(key) ) {
3387 TALLOC_FREE( data );
3391 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3397 /* remove a specific key (and all subkeys) */
3399 for ( i=0; i<data->num_keys; i++ ) {
3400 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3401 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3402 data->keys[i].name));
3404 TALLOC_FREE( data->keys[i].name );
3405 TALLOC_FREE( data->keys[i].values );
3407 /* mark the slot as empty */
3409 ZERO_STRUCTP( &data->keys[i] );
3413 /* find the first empty slot */
3415 for ( i=0; i<data->num_keys; i++ ) {
3416 if ( !data->keys[i].name ) {
3423 if ( i == data->num_keys )
3424 /* nothing was removed */
3425 return WERR_INVALID_PARAM;
3427 /* move everything down */
3429 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3430 if ( data->keys[i].name ) {
3431 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3432 ZERO_STRUCTP( &data->keys[i] );
3440 data->num_keys -= removed_keys;
3442 /* sanity check to see if anything is left */
3444 if ( !data->num_keys ) {
3445 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3447 SAFE_FREE( data->keys );
3448 ZERO_STRUCTP( data );
3454 /****************************************************************************
3455 ***************************************************************************/
3457 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3459 WERROR result = WERR_OK;
3462 /* we must have names on non-zero length */
3464 if ( !key || !*key|| !value || !*value )
3465 return WERR_INVALID_NAME;
3467 /* find the printer key first */
3469 key_index = lookup_printerkey( p2->data, key );
3470 if ( key_index == -1 )
3473 /* make sure the value exists so we can return the correct error code */
3475 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3476 return WERR_BADFILE;
3478 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3480 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3486 /****************************************************************************
3487 ***************************************************************************/
3489 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3490 uint32 type, uint8 *data, int real_len )
3492 WERROR result = WERR_OK;
3495 /* we must have names on non-zero length */
3497 if ( !key || !*key|| !value || !*value )
3498 return WERR_INVALID_NAME;
3500 /* find the printer key first */
3502 key_index = lookup_printerkey( p2->data, key );
3503 if ( key_index == -1 )
3504 key_index = add_new_printer_key( p2->data, key );
3506 if ( key_index == -1 )
3509 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3510 type, (const char *)data, real_len );
3512 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3513 key, value, type, real_len ));
3518 /****************************************************************************
3519 ***************************************************************************/
3521 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3525 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3528 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3531 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3534 /****************************************************************************
3535 Unpack a list of registry values frem the TDB
3536 ***************************************************************************/
3538 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3542 pstring string, valuename, keyname;
3546 REGISTRY_VALUE *regval_p;
3549 /* add the "PrinterDriverData" key first for performance reasons */
3551 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3553 /* loop and unpack the rest of the registry values */
3557 /* check to see if there are any more registry values */
3560 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3564 /* unpack the next regval */
3566 len += tdb_unpack(buf+len, buflen-len, "fdB",
3572 /* lookup for subkey names which have a type of REG_NONE */
3573 /* there's no data with this entry */
3575 if ( type == REG_NONE ) {
3576 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3577 add_new_printer_key( printer_data, string );
3582 * break of the keyname from the value name.
3583 * Valuenames can have embedded '\'s so be careful.
3584 * only support one level of keys. See the
3585 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3589 str = strchr_m( string, '\\');
3591 /* Put in "PrinterDriverData" is no key specified */
3594 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3595 pstrcpy( valuename, string );
3599 pstrcpy( keyname, string );
3600 pstrcpy( valuename, str+1 );
3603 /* see if we need a new key */
3605 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3606 key_index = add_new_printer_key( printer_data, keyname );
3608 if ( key_index == -1 ) {
3609 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3614 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3616 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3617 Thanks to Martin Zielinski for the hint. */
3619 if ( type == REG_BINARY &&
3620 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3621 strequal( valuename, "objectGUID" ) )
3624 UNISTR2 unistr_guid;
3626 ZERO_STRUCT( unistr_guid );
3628 /* convert the GUID to a UNICODE string */
3630 memcpy( &guid, data_p, sizeof(struct GUID) );
3632 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3633 UNI_STR_TERMINATE );
3635 regval_ctr_addvalue( printer_data->keys[key_index].values,
3637 (const char *)unistr_guid.buffer,
3638 unistr_guid.uni_str_len*2 );
3643 regval_ctr_addvalue( printer_data->keys[key_index].values,
3644 valuename, type, (const char *)data_p,
3649 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3656 /****************************************************************************
3657 ***************************************************************************/
3659 static void map_to_os2_driver(fstring drivername)
3661 static bool initialised=False;
3662 static fstring last_from,last_to;
3663 char *mapfile = lp_os2_driver_map();
3664 char **lines = NULL;
3668 if (!strlen(drivername))
3675 *last_from = *last_to = 0;
3679 if (strequal(drivername,last_from)) {
3680 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3681 fstrcpy(drivername,last_to);
3685 lines = file_lines_load(mapfile, &numlines,0);
3686 if (numlines == 0 || lines == NULL) {
3687 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3692 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3694 for( i = 0; i < numlines; i++) {
3695 char *nt_name = lines[i];
3696 char *os2_name = strchr(nt_name,'=');
3703 while (isspace(*nt_name))
3706 if (!*nt_name || strchr("#;",*nt_name))
3710 int l = strlen(nt_name);
3711 while (l && isspace(nt_name[l-1])) {
3717 while (isspace(*os2_name))
3721 int l = strlen(os2_name);
3722 while (l && isspace(os2_name[l-1])) {
3728 if (strequal(nt_name,drivername)) {
3729 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3730 fstrcpy(last_from,drivername);
3731 fstrcpy(last_to,os2_name);
3732 fstrcpy(drivername,os2_name);
3733 file_lines_free(lines);
3738 file_lines_free(lines);
3741 /****************************************************************************
3742 Get a default printer info 2 struct.
3743 ****************************************************************************/
3744 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3746 int snum = lp_servicenumber(sharename);
3748 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3749 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3750 servername, sharename);
3751 fstrcpy(info->sharename, sharename);
3752 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3754 /* by setting the driver name to an empty string, a local NT admin
3755 can now run the **local** APW to install a local printer driver
3756 for a Samba shared printer in 2.2. Without this, drivers **must** be
3757 installed on the Samba server for NT clients --jerry */
3758 #if 0 /* JERRY --do not uncomment-- */
3759 if (!*info->drivername)
3760 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3764 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3766 pstrcpy(info->comment, "");
3767 fstrcpy(info->printprocessor, "winprint");
3768 fstrcpy(info->datatype, "RAW");
3771 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3772 /* Pull the location and comment strings from cups if we don't
3774 if ( !strlen(info->location) || !strlen(info->comment) )
3775 cups_pull_comment_location( info );
3779 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3781 info->starttime = 0; /* Minutes since 12:00am GMT */
3782 info->untiltime = 0; /* Minutes since 12:00am GMT */
3784 info->default_priority = 1;
3785 info->setuptime = (uint32)time(NULL);
3788 * I changed this as I think it is better to have a generic
3789 * DEVMODE than to crash Win2k explorer.exe --jerry
3790 * See the HP Deskjet 990c Win2k drivers for an example.
3792 * However the default devmode appears to cause problems
3793 * with the HP CLJ 8500 PCL driver. Hence the addition of
3794 * the "default devmode" parameter --jerry 22/01/2002
3797 if (lp_default_devmode(snum)) {
3798 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3802 info->devmode = NULL;
3805 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3813 free_nt_devicemode(&info->devmode);
3815 return WERR_ACCESS_DENIED;
3818 /****************************************************************************
3819 ****************************************************************************/
3820 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3823 int snum = lp_servicenumber(sharename);
3824 TDB_DATA kbuf, dbuf;
3825 fstring printername;
3826 char adevice[MAXDEVICENAME];
3828 kbuf = make_printer_tdbkey( sharename );
3830 dbuf = tdb_fetch(tdb_printers, kbuf);
3832 return get_a_printer_2_default(info, servername, sharename);
3835 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3838 &info->default_priority,
3845 &info->c_setprinter,
3855 info->printprocessor,
3859 /* Samba has to have shared raw drivers. */
3860 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3861 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3863 /* Restore the stripped strings. */
3864 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3866 if ( lp_force_printername(snum) ) {
3867 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3869 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3872 fstrcpy(info->printername, printername);
3875 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3876 /* Pull the location and comment strings from cups if we don't
3878 if ( !strlen(info->location) || !strlen(info->comment) )
3879 cups_pull_comment_location( info );
3883 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3886 * Some client drivers freak out if there is a NULL devmode
3887 * (probably the driver is not checking before accessing
3888 * the devmode pointer) --jerry
3890 * See comments in get_a_printer_2_default()
3893 if (lp_default_devmode(snum) && !info->devmode) {
3894 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3896 info->devmode = construct_nt_devicemode(printername);
3899 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3900 if (info->devmode) {
3901 fstrcpy(info->devmode->devicename, adevice);
3904 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3905 DEBUG(0,("unpack_values: talloc() failed!\n"));
3906 SAFE_FREE(dbuf.dptr);
3909 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3911 /* This will get the current RPC talloc context, but we should be
3912 passing this as a parameter... fixme... JRA ! */
3914 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3915 SAFE_FREE(dbuf.dptr);
3919 /* Fix for OS/2 drivers. */
3921 if (get_remote_arch() == RA_OS2) {
3922 map_to_os2_driver(info->drivername);
3925 SAFE_FREE(dbuf.dptr);
3927 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3928 sharename, info->printername, info->drivername));
3933 /****************************************************************************
3934 Debugging function, dump at level 6 the struct in the logs.
3935 ****************************************************************************/
3936 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3939 NT_PRINTER_INFO_LEVEL_2 *info2;
3941 DEBUG(106,("Dumping printer at level [%d]\n", level));
3946 if (printer->info_2 == NULL)
3950 info2=printer->info_2;
3952 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3953 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3954 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3955 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3956 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3957 DEBUGADD(106,("status:[%d]\n", info2->status));
3958 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3959 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3960 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3961 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3962 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3964 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3965 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3966 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3967 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3968 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3969 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3970 DEBUGADD(106,("location:[%s]\n", info2->location));
3971 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3972 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3973 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3974 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3980 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3988 /****************************************************************************
3989 Update the changeid time.
3990 This is SO NASTY as some drivers need this to change, others need it
3991 static. This value will change every second, and I must hope that this
3992 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3994 ****************************************************************************/
3996 static uint32 rev_changeid(void)
4000 get_process_uptime(&tv);
4003 /* Return changeid as msec since spooler restart */
4004 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4007 * This setting seems to work well but is too untested
4008 * to replace the above calculation. Left in for experiementation
4009 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4011 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4017 * The function below are the high level ones.
4018 * only those ones must be called from the spoolss code.
4022 /****************************************************************************
4023 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4024 ****************************************************************************/
4026 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4030 dump_a_printer(printer, level);
4036 * Update the changestamp. Emperical tests show that the
4037 * ChangeID is always updated,but c_setprinter is
4038 * global spooler variable (not per printer).
4041 /* ChangeID **must** be increasing over the lifetime
4042 of client's spoolss service in order for the
4043 client's cache to show updates */
4045 printer->info_2->changeid = rev_changeid();
4048 * Because one day someone will ask:
4049 * NT->NT An admin connection to a remote
4050 * printer show changes imeediately in
4051 * the properities dialog
4053 * A non-admin connection will only show the
4054 * changes after viewing the properites page
4055 * 2 times. Seems to be related to a
4056 * race condition in the client between the spooler
4057 * updating the local cache and the Explorer.exe GUI
4058 * actually displaying the properties.
4060 * This is fixed in Win2k. admin/non-admin
4061 * connections both display changes immediately.
4066 result=update_a_printer_2(printer->info_2);
4071 result=WERR_UNKNOWN_LEVEL;
4078 /****************************************************************************
4079 Initialize printer devmode & data with previously saved driver init values.
4080 ****************************************************************************/
4082 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4087 NT_PRINTER_INFO_LEVEL_2 info;
4093 * Delete any printer data 'values' already set. When called for driver
4094 * replace, there will generally be some, but during an add printer, there
4095 * should not be any (if there are delete them).
4098 if ( info_ptr->data )
4099 delete_all_printer_data( info_ptr, "" );
4101 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4103 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4106 * When changing to a driver that has no init info in the tdb, remove
4107 * the previous drivers init info and leave the new on blank.
4109 free_nt_devicemode(&info_ptr->devmode);
4114 * Get the saved DEVMODE..
4117 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4120 * The saved DEVMODE contains the devicename from the printer used during
4121 * the initialization save. Change it to reflect the new printer.
4124 if ( info.devmode ) {
4125 ZERO_STRUCT(info.devmode->devicename);
4126 fstrcpy(info.devmode->devicename, info_ptr->printername);
4130 * NT/2k does not change out the entire DeviceMode of a printer
4131 * when changing the driver. Only the driverextra, private, &
4132 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4134 * Later examination revealed that Windows NT/2k does reset the
4135 * the printer's device mode, bit **only** when you change a
4136 * property of the device mode such as the page orientation.
4141 /* Bind the saved DEVMODE to the new the printer */
4143 free_nt_devicemode(&info_ptr->devmode);
4144 info_ptr->devmode = info.devmode;
4146 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4147 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4149 /* Add the printer data 'values' to the new printer */
4151 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4152 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4156 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4159 SAFE_FREE(dbuf.dptr);
4164 /****************************************************************************
4165 Initialize printer devmode & data with previously saved driver init values.
4166 When a printer is created using AddPrinter, the drivername bound to the
4167 printer is used to lookup previously saved driver initialization info, which
4168 is bound to the new printer.
4169 ****************************************************************************/
4171 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4173 bool result = False;
4177 result = set_driver_init_2(printer->info_2);
4181 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4189 /****************************************************************************
4190 Delete driver init data stored for a specified driver
4191 ****************************************************************************/
4193 bool del_driver_init(char *drivername)
4197 if (!drivername || !*drivername) {
4198 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4202 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4204 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4206 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4209 /****************************************************************************
4210 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4211 in the tdb. Note: this is different from the driver entry and the printer
4212 entry. There should be a single driver init entry for each driver regardless
4213 of whether it was installed from NT or 2K. Technically, they should be
4214 different, but they work out to the same struct.
4215 ****************************************************************************/
4217 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4221 int buflen, len, ret;
4229 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4231 len += pack_values( info->data, buf+len, buflen-len );
4234 buf = (uint8 *)SMB_REALLOC(buf, len);
4236 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4244 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4249 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4253 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4257 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4258 info->sharename, info->drivername));
4263 /****************************************************************************
4264 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4265 ****************************************************************************/
4267 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4271 dump_a_printer(printer, level);
4275 result = update_driver_init_2(printer->info_2);
4285 /****************************************************************************
4286 Convert the printer data value, a REG_BINARY array, into an initialization
4287 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4288 got to keep the endians happy :).
4289 ****************************************************************************/
4291 static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4293 bool result = False;
4297 ZERO_STRUCT(devmode);
4299 prs_init(&ps, 0, ctx, UNMARSHALL);
4300 ps.data_p = (char *)data;
4301 ps.buffer_size = data_len;
4303 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4304 result = convert_devicemode("", &devmode, &nt_devmode);
4306 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4311 /****************************************************************************
4312 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4314 1. Use the driver's config DLL to this UNC printername and:
4315 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4316 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4317 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4319 The last step triggers saving the "driver initialization" information for
4320 this printer into the tdb. Later, new printers that use this driver will
4321 have this initialization information bound to them. This simulates the
4322 driver initialization, as if it had run on the Samba server (as it would
4325 The Win32 client side code requirement sucks! But until we can run arbitrary
4326 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4328 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4329 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4330 about it and you will realize why. JRR 010720
4331 ****************************************************************************/
4333 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4335 WERROR status = WERR_OK;
4336 TALLOC_CTX *ctx = NULL;
4337 NT_DEVICEMODE *nt_devmode = NULL;
4338 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4341 * When the DEVMODE is already set on the printer, don't try to unpack it.
4343 DEBUG(8,("save_driver_init_2: Enter...\n"));
4345 if ( !printer->info_2->devmode && data_len ) {
4347 * Set devmode on printer info, so entire printer initialization can be
4351 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4354 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4355 status = WERR_NOMEM;
4359 ZERO_STRUCTP(nt_devmode);
4362 * The DEVMODE is held in the 'data' component of the param in raw binary.
4363 * Convert it to to a devmode structure
4365 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4366 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4367 status = WERR_INVALID_PARAM;
4371 printer->info_2->devmode = nt_devmode;
4375 * Pack up and add (or update) the DEVMODE and any current printer data to
4376 * a 'driver init' element in the tdb
4380 if ( update_driver_init(printer, 2) != 0 ) {
4381 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4382 status = WERR_NOMEM;
4387 * If driver initialization info was successfully saved, set the current
4388 * printer to match it. This allows initialization of the current printer
4389 * as well as the driver.
4391 status = mod_a_printer(printer, 2);
4392 if (!W_ERROR_IS_OK(status)) {
4393 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4394 printer->info_2->printername));
4398 talloc_destroy(ctx);
4399 free_nt_devicemode( &nt_devmode );
4401 printer->info_2->devmode = tmp_devmode;
4406 /****************************************************************************
4407 Update the driver init info (DEVMODE and specifics) for a printer
4408 ****************************************************************************/
4410 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4412 WERROR status = WERR_OK;
4416 status = save_driver_init_2( printer, data, data_len );
4419 status = WERR_UNKNOWN_LEVEL;
4426 /****************************************************************************
4427 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4429 Previously the code had a memory allocation problem because it always
4430 used the TALLOC_CTX from the Printer_entry*. This context lasts
4431 as a long as the original handle is open. So if the client made a lot
4432 of getprinter[data]() calls, the memory usage would climb. Now we use
4433 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4434 still use the Printer_entry->ctx for maintaining the cache copy though
4435 since that object must live as long as the handle by definition.
4438 ****************************************************************************/
4440 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4441 const char *sharename)
4446 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4448 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4449 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4455 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4456 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4457 TALLOC_FREE( *pp_printer );
4462 fstrcpy( servername, print_hnd->servername );
4464 fstrcpy( servername, "%L" );
4465 standard_sub_basic( "", "", servername,
4466 sizeof(servername)-1 );
4469 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4472 /* we have a new printer now. Save it with this handle */
4474 if ( !W_ERROR_IS_OK(result) ) {
4475 TALLOC_FREE( *pp_printer );
4476 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4477 sharename, (unsigned int)level, dos_errstr(result)));
4481 dump_a_printer( *pp_printer, level);
4486 TALLOC_FREE( *pp_printer );
4487 return WERR_UNKNOWN_LEVEL;
4493 /****************************************************************************
4494 Deletes a NT_PRINTER_INFO_LEVEL struct.
4495 ****************************************************************************/
4497 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4499 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4506 if ( printer->info_2 )
4507 free_nt_printer_info_level_2(&printer->info_2);
4511 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4515 TALLOC_FREE(*pp_printer);
4520 /****************************************************************************
4521 ****************************************************************************/
4522 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4525 DEBUG(104,("adding a printer at level [%d]\n", level));
4526 dump_a_printer_driver(driver, level);
4530 result=add_a_printer_driver_3(driver.info_3);
4534 result=add_a_printer_driver_6(driver.info_6);
4544 /****************************************************************************
4545 ****************************************************************************/
4547 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4548 fstring drivername, const char *architecture, uint32 version)
4554 /* Sometime we just want any version of the driver */
4556 if ( version == DRIVER_ANY_VERSION ) {
4557 /* look for Win2k first and then for NT4 */
4558 result = get_a_printer_driver_3(&driver->info_3, drivername,
4561 if ( !W_ERROR_IS_OK(result) ) {
4562 result = get_a_printer_driver_3( &driver->info_3,
4563 drivername, architecture, 2 );
4566 result = get_a_printer_driver_3(&driver->info_3, drivername,
4567 architecture, version);
4576 if (W_ERROR_IS_OK(result))
4577 dump_a_printer_driver(*driver, level);
4582 /****************************************************************************
4583 ****************************************************************************/
4584 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4591 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4592 if (driver.info_3 != NULL)
4594 info3=driver.info_3;
4595 SAFE_FREE(info3->dependentfiles);
4596 ZERO_STRUCTP(info3);
4606 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4607 if (driver.info_6 != NULL) {
4608 info6=driver.info_6;
4609 SAFE_FREE(info6->dependentfiles);
4610 SAFE_FREE(info6->previousnames);
4611 ZERO_STRUCTP(info6);
4627 /****************************************************************************
4628 Determine whether or not a particular driver is currently assigned
4630 ****************************************************************************/
4632 bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4635 int n_services = lp_numservices();
4636 NT_PRINTER_INFO_LEVEL *printer = NULL;
4637 bool in_use = False;
4642 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4644 /* loop through the printers.tdb and check for the drivername */
4646 for (snum=0; snum<n_services && !in_use; snum++) {
4647 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4650 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4653 if ( strequal(info_3->name, printer->info_2->drivername) )
4656 free_a_printer( &printer, 2 );
4659 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4662 NT_PRINTER_DRIVER_INFO_LEVEL d;
4665 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4667 /* we can still remove the driver if there is one of
4668 "Windows NT x86" version 2 or 3 left */
4670 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4671 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4674 switch ( info_3->cversion ) {
4676 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4679 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4682 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4684 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4689 /* now check the error code */
4691 if ( W_ERROR_IS_OK(werr) ) {
4692 /* it's ok to remove the driver, we have other architctures left */
4694 free_a_printer_driver( d, 3 );
4698 /* report that the driver is not in use by default */
4704 /**********************************************************************
4705 Check to see if a ogiven file is in use by *info
4706 *********************************************************************/
4708 static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4715 if ( strequal(file, info->driverpath) )
4718 if ( strequal(file, info->datafile) )
4721 if ( strequal(file, info->configfile) )
4724 if ( strequal(file, info->helpfile) )
4727 /* see of there are any dependent files to examine */
4729 if ( !info->dependentfiles )
4732 while ( *info->dependentfiles[i] ) {
4733 if ( strequal(file, info->dependentfiles[i]) )
4742 /**********************************************************************
4743 Utility function to remove the dependent file pointed to by the
4744 input parameter from the list
4745 *********************************************************************/
4747 static void trim_dependent_file( fstring files[], int idx )
4750 /* bump everything down a slot */
4752 while( *files[idx+1] ) {
4753 fstrcpy( files[idx], files[idx+1] );
4762 /**********************************************************************
4763 Check if any of the files used by src are also used by drv
4764 *********************************************************************/
4766 static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4767 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4769 bool in_use = False;
4775 /* check each file. Remove it from the src structure if it overlaps */
4777 if ( drv_file_in_use(src->driverpath, drv) ) {
4779 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4780 fstrcpy( src->driverpath, "" );
4783 if ( drv_file_in_use(src->datafile, drv) ) {
4785 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4786 fstrcpy( src->datafile, "" );
4789 if ( drv_file_in_use(src->configfile, drv) ) {
4791 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4792 fstrcpy( src->configfile, "" );
4795 if ( drv_file_in_use(src->helpfile, drv) ) {
4797 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4798 fstrcpy( src->helpfile, "" );
4801 /* are there any dependentfiles to examine? */
4803 if ( !src->dependentfiles )
4806 while ( *src->dependentfiles[i] ) {
4807 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4809 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4810 trim_dependent_file( src->dependentfiles, i );
4818 /****************************************************************************
4819 Determine whether or not a particular driver files are currently being
4820 used by any other driver.
4822 Return value is True if any files were in use by other drivers
4823 and False otherwise.
4825 Upon return, *info has been modified to only contain the driver files
4826 which are not in use
4827 ****************************************************************************/
4829 bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4834 fstring *list = NULL;
4835 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4840 version = info->cversion;
4842 /* loop over all driver versions */
4844 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4846 /* get the list of drivers */
4849 ndrivers = get_ntdrivers(&list, info->environment, version);
4851 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4852 ndrivers, info->environment, version));
4854 /* check each driver for overlap in files */
4856 for (i=0; i<ndrivers; i++) {
4857 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4859 ZERO_STRUCT(driver);
4861 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4866 /* check if d2 uses any files from d1 */
4867 /* only if this is a different driver than the one being deleted */
4869 if ( !strequal(info->name, driver.info_3->name) ) {
4870 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4871 free_a_printer_driver(driver, 3);
4877 free_a_printer_driver(driver, 3);
4882 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4884 driver.info_3 = info;
4886 if ( DEBUGLEVEL >= 20 )
4887 dump_a_printer_driver( driver, 3 );
4892 /****************************************************************************
4893 Actually delete the driver files. Make sure that
4894 printer_driver_files_in_use() return False before calling
4896 ****************************************************************************/
4898 static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4903 connection_struct *conn;
4912 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4915 * Connect to the print$ share under the same account as the
4916 * user connected to the rpc pipe. Note we must be root to
4920 null_pw = data_blob_null;
4921 fstrcpy(res_type, "A:");
4923 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4927 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4931 if ( !CAN_WRITE(conn) ) {
4932 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4936 /* Save who we are - we are temporarily becoming the connection user. */
4938 if ( !become_user(conn, conn->vuid) ) {
4939 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4943 /* now delete the files; must strip the '\print$' string from
4946 if ( *info_3->driverpath ) {
4947 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4949 driver_unix_convert(conn,file,&st);
4950 DEBUG(10,("deleting driverfile [%s]\n", s));
4951 unlink_internals(conn, NULL, 0, file, False);
4955 if ( *info_3->configfile ) {
4956 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4958 driver_unix_convert(conn,file,&st);
4959 DEBUG(10,("deleting configfile [%s]\n", s));
4960 unlink_internals(conn, NULL, 0, file, False);
4964 if ( *info_3->datafile ) {
4965 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4967 driver_unix_convert(conn,file,&st);
4968 DEBUG(10,("deleting datafile [%s]\n", s));
4969 unlink_internals(conn, NULL, 0, file, False);
4973 if ( *info_3->helpfile ) {
4974 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4976 driver_unix_convert(conn,file,&st);
4977 DEBUG(10,("deleting helpfile [%s]\n", s));
4978 unlink_internals(conn, NULL, 0, file, False);
4982 /* check if we are done removing files */
4984 if ( info_3->dependentfiles ) {
4985 while ( info_3->dependentfiles[i][0] ) {
4988 /* bypass the "\print$" portion of the path */
4990 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4992 driver_unix_convert(conn,file,&st);
4993 DEBUG(10,("deleting dependent file [%s]\n", file));
4994 unlink_internals(conn, NULL, 0, file, False);
5006 /****************************************************************************
5007 Remove a printer driver from the TDB. This assumes that the the driver was
5008 previously looked up.
5009 ***************************************************************************/
5011 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5012 uint32 version, bool delete_files )
5017 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5019 /* delete the tdb data first */
5021 arch = get_short_archi(info_3->environment);
5023 return WERR_UNKNOWN_PRINTER_DRIVER;
5025 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5026 arch, version, info_3->name);
5028 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5029 key, delete_files ? "TRUE" : "FALSE" ));
5031 ctr.info_3 = info_3;
5032 dump_a_printer_driver( ctr, 3 );
5034 /* check if the driver actually exists for this environment */
5036 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5038 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5039 return WERR_UNKNOWN_PRINTER_DRIVER;
5042 SAFE_FREE( dbuf.dptr );
5044 /* ok... the driver exists so the delete should return success */
5046 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5047 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5048 return WERR_ACCESS_DENIED;
5052 * now delete any associated files if delete_files == True
5053 * even if this part failes, we return succes because the
5054 * driver doesn not exist any more
5058 delete_driver_files( info_3, user );
5061 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5066 /****************************************************************************
5067 Store a security desc for a printer.
5068 ****************************************************************************/
5070 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5072 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5073 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5075 TALLOC_CTX *mem_ctx = NULL;
5079 mem_ctx = talloc_init("nt_printing_setsec");
5080 if (mem_ctx == NULL)
5083 /* The old owner and group sids of the security descriptor are not
5084 present when new ACEs are added or removed by changing printer
5085 permissions through NT. If they are NULL in the new security
5086 descriptor then copy them over from the old one. */
5088 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5089 DOM_SID *owner_sid, *group_sid;
5090 SEC_ACL *dacl, *sacl;
5091 SEC_DESC *psd = NULL;
5094 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5095 status = WERR_NOMEM;
5099 /* Pick out correct owner and group sids */
5101 owner_sid = secdesc_ctr->sd->owner_sid ?
5102 secdesc_ctr->sd->owner_sid :
5103 old_secdesc_ctr->sd->owner_sid;
5105 group_sid = secdesc_ctr->sd->group_sid ?
5106 secdesc_ctr->sd->group_sid :
5107 old_secdesc_ctr->sd->group_sid;
5109 dacl = secdesc_ctr->sd->dacl ?
5110 secdesc_ctr->sd->dacl :
5111 old_secdesc_ctr->sd->dacl;
5113 sacl = secdesc_ctr->sd->sacl ?
5114 secdesc_ctr->sd->sacl :
5115 old_secdesc_ctr->sd->sacl;
5117 /* Make a deep copy of the security descriptor */
5119 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5120 owner_sid, group_sid,
5126 status = WERR_NOMEM;
5130 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5133 if (!new_secdesc_ctr) {
5134 new_secdesc_ctr = secdesc_ctr;
5137 /* Store the security descriptor in a tdb */
5139 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5140 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5142 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5144 status = WERR_BADFUNC;
5148 kbuf = make_printers_secdesc_tdbkey( sharename );
5150 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5153 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5154 status = WERR_BADFUNC;
5157 /* Free malloc'ed memory */
5163 talloc_destroy(mem_ctx);
5167 /****************************************************************************
5168 Construct a default security descriptor buffer for a printer.
5169 ****************************************************************************/
5171 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5173 SEC_ACE ace[5]; /* max number of ace entries */
5176 SEC_ACL *psa = NULL;
5177 SEC_DESC_BUF *sdb = NULL;
5178 SEC_DESC *psd = NULL;
5182 /* Create an ACE where Everyone is allowed to print */
5184 init_sec_access(&sa, PRINTER_ACE_PRINT);
5185 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5186 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5188 /* Add the domain admins group if we are a DC */
5191 DOM_SID domadmins_sid;
5193 sid_copy(&domadmins_sid, get_global_sam_sid());
5194 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5196 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5197 init_sec_ace(&ace[i++], &domadmins_sid,
5198 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5199 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5200 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5201 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5203 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5204 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5206 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5207 init_sec_ace(&ace[i++], &adm_sid,
5208 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5209 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5210 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5211 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5214 /* add BUILTIN\Administrators as FULL CONTROL */
5216 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5217 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5218 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5219 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5220 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5221 SEC_ACE_TYPE_ACCESS_ALLOWED,
5222 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5224 /* Make the security descriptor owned by the BUILTIN\Administrators */
5226 /* The ACL revision number in rpc_secdesc.h differs from the one
5227 created by NT when setting ACE entries in printer
5228 descriptors. NT4 complains about the property being edited by a
5231 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5232 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5233 &global_sid_Builtin_Administrators,
5234 &global_sid_Builtin_Administrators,
5235 NULL, psa, &sd_size);
5239 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5243 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5245 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5246 (unsigned int)sd_size));
5251 /****************************************************************************
5252 Get a security desc for a printer.
5253 ****************************************************************************/
5255 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5261 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5262 sharename = temp + 1;
5267 /* Fetch security descriptor from tdb */
5269 kbuf = make_printers_secdesc_tdbkey( sharename );
5271 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5272 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5276 DEBUG(4,("using default secdesc for %s\n", sharename));
5278 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5282 /* Save default security descriptor for later */
5284 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5285 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5287 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5288 tdb_prs_store(tdb_printers, kbuf, &ps);
5298 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5299 this security descriptor has been created when winbindd was
5300 down. Take ownership of security descriptor. */
5302 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5305 /* Change sd owner to workgroup administrator */
5307 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5308 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5309 SEC_DESC *psd = NULL;
5314 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5316 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5318 (*secdesc_ctr)->sd->group_sid,
5319 (*secdesc_ctr)->sd->sacl,
5320 (*secdesc_ctr)->sd->dacl,
5327 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5328 if (!new_secdesc_ctr) {
5332 /* Swap with other one */
5334 *secdesc_ctr = new_secdesc_ctr;
5338 nt_printing_setsec(sharename, *secdesc_ctr);
5342 if (DEBUGLEVEL >= 10) {
5343 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5346 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5347 sharename, the_acl->num_aces));
5349 for (i = 0; i < the_acl->num_aces; i++) {
5352 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5354 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5355 the_acl->aces[i].type, the_acl->aces[i].flags,
5356 the_acl->aces[i].access_mask));
5365 1: level not implemented
5366 2: file doesn't exist
5367 3: can't allocate memory
5368 4: can't free memory
5369 5: non existant struct
5373 A printer and a printer driver are 2 different things.
5374 NT manages them separatelly, Samba does the same.
5375 Why ? Simply because it's easier and it makes sense !
5377 Now explanation: You have 3 printers behind your samba server,
5378 2 of them are the same make and model (laser A and B). But laser B
5379 has an 3000 sheet feeder and laser A doesn't such an option.
5380 Your third printer is an old dot-matrix model for the accounting :-).
5382 If the /usr/local/samba/lib directory (default dir), you will have
5383 5 files to describe all of this.
5385 3 files for the printers (1 by printer):
5388 NTprinter_accounting
5389 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5390 NTdriver_printer model X
5391 NTdriver_printer model Y
5393 jfm: I should use this comment for the text file to explain
5394 same thing for the forms BTW.
5395 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5399 /* Convert generic access rights to printer object specific access rights.
5400 It turns out that NT4 security descriptors use generic access rights and
5401 NT5 the object specific ones. */
5403 void map_printer_permissions(SEC_DESC *sd)
5407 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5408 se_map_generic(&sd->dacl->aces[i].access_mask,
5409 &printer_generic_mapping);
5413 /****************************************************************************
5414 Check a user has permissions to perform the given operation. We use the
5415 permission constants defined in include/rpc_spoolss.h to check the various
5416 actions we perform when checking printer access.
5418 PRINTER_ACCESS_ADMINISTER:
5419 print_queue_pause, print_queue_resume, update_printer_sec,
5420 update_printer, spoolss_addprinterex_level_2,
5421 _spoolss_setprinterdata
5426 JOB_ACCESS_ADMINISTER:
5427 print_job_delete, print_job_pause, print_job_resume,
5430 Try access control in the following order (for performance reasons):
5431 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5432 2) check security descriptor (bit comparisons in memory)
5433 3) "printer admins" (may result in numerous calls to winbind)
5435 ****************************************************************************/
5436 bool print_access_check(struct current_user *user, int snum, int access_type)
5438 SEC_DESC_BUF *secdesc = NULL;
5439 uint32 access_granted;
5443 TALLOC_CTX *mem_ctx = NULL;
5444 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5446 /* If user is NULL then use the current_user structure */
5449 user = ¤t_user;
5451 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5453 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5457 /* Get printer name */
5459 pname = PRINTERNAME(snum);
5461 if (!pname || !*pname) {
5466 /* Get printer security descriptor */
5468 if(!(mem_ctx = talloc_init("print_access_check"))) {
5473 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5474 talloc_destroy(mem_ctx);
5479 if (access_type == JOB_ACCESS_ADMINISTER) {
5480 SEC_DESC_BUF *parent_secdesc = secdesc;
5482 /* Create a child security descriptor to check permissions
5483 against. This is because print jobs are child objects
5484 objects of a printer. */
5486 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5489 talloc_destroy(mem_ctx);
5494 /* Now this is the bit that really confuses me. The access
5495 type needs to be changed from JOB_ACCESS_ADMINISTER to
5496 PRINTER_ACCESS_ADMINISTER for this to work. Something
5497 to do with the child (job) object becoming like a
5500 access_type = PRINTER_ACCESS_ADMINISTER;
5505 map_printer_permissions(secdesc->sd);
5507 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5508 &access_granted, &status);
5510 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5512 /* see if we need to try the printer admin list */
5514 if ((access_granted == 0) &&
5515 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5516 user->nt_user_token,
5517 lp_printer_admin(snum)))) {
5518 talloc_destroy(mem_ctx);
5522 talloc_destroy(mem_ctx);
5531 /****************************************************************************
5532 Check the time parameters allow a print operation.
5533 *****************************************************************************/
5535 bool print_time_access_check(const char *servicename)
5537 NT_PRINTER_INFO_LEVEL *printer = NULL;
5539 time_t now = time(NULL);
5543 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5546 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5550 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5552 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5555 free_a_printer(&printer, 2);
5563 /****************************************************************************
5564 Fill in the servername sent in the _spoolss_open_printer_ex() call
5565 ****************************************************************************/
5567 char* get_server_name( Printer_entry *printer )
5569 return printer->servername;