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 GENERIC_MAPPING printer_generic_mapping = {
52 STANDARD_MAPPING printer_std_mapping = {
59 /* Map generic permissions to print server object specific permissions */
61 GENERIC_MAPPING printserver_generic_mapping = {
68 STANDARD_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(lock_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 lock_path("ntdrivers.tdb"), strerror(errno) ));
563 tdb_close(tdb_printers);
564 tdb_printers = tdb_open_log(lock_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 lock_path("ntprinters.tdb"), strerror(errno) ));
572 tdb_close(tdb_forms);
573 tdb_forms = tdb_open_log(lock_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 lock_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(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)-1);
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)-1);
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)-1);
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)-1);
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)-1);
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;
1750 memset(inbuf, '\0', sizeof(inbuf));
1751 memset(outbuf, '\0', sizeof(outbuf));
1755 driver=driver_abstract.info_3;
1756 else if (level==6) {
1757 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1758 driver = &converted_driver;
1760 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1761 return WERR_UNKNOWN_LEVEL;
1764 architecture = get_short_archi(driver->environment);
1765 if (!architecture) {
1766 return WERR_UNKNOWN_PRINTER_DRIVER;
1770 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1771 * Note we must be root to do this.
1774 null_pw = data_blob_null;
1775 fstrcpy(res_type, "A:");
1777 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1781 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1782 *perr = ntstatus_to_werror(nt_status);
1783 return WERR_NO_SUCH_SHARE;
1787 * Save who we are - we are temporarily becoming the connection user.
1790 if (!become_user(conn, conn->vuid)) {
1791 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1792 return WERR_ACCESS_DENIED;
1796 * make the directories version and version\driver_name
1797 * under the architecture directory.
1799 DEBUG(5,("Creating first directory\n"));
1800 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1801 driver_unix_convert(conn,new_dir,&st);
1802 create_directory(conn, new_dir);
1804 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1805 * listed for this driver which has already been moved, skip it (note:
1806 * drivers may list the same file name several times. Then check if the
1807 * file already exists in archi\cversion\, if so, check that the version
1808 * info (or time stamps if version info is unavailable) is newer (or the
1809 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1810 * Otherwise, delete the file.
1812 * If a file is not moved to archi\cversion\ because of an error, all the
1813 * rest of the 'unmoved' driver files are removed from archi\. If one or
1814 * more of the driver's files was already moved to archi\cversion\, it
1815 * potentially leaves the driver in a partially updated state. Version
1816 * trauma will most likely occur if an client attempts to use any printer
1817 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1818 * done is appropriate... later JRR
1821 DEBUG(5,("Moving files now !\n"));
1823 if (driver->driverpath && strlen(driver->driverpath)) {
1824 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1825 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1826 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1827 driver_unix_convert(conn,new_name,&st);
1828 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1829 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1830 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1831 new_name, old_name));
1832 *perr = WERR_ACCESS_DENIED;
1838 if (driver->datafile && strlen(driver->datafile)) {
1839 if (!strequal(driver->datafile, driver->driverpath)) {
1840 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1841 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1842 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1843 driver_unix_convert(conn,new_name,&st);
1844 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1845 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1846 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1847 new_name, old_name));
1848 *perr = WERR_ACCESS_DENIED;
1855 if (driver->configfile && strlen(driver->configfile)) {
1856 if (!strequal(driver->configfile, driver->driverpath) &&
1857 !strequal(driver->configfile, driver->datafile)) {
1858 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1859 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1860 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1861 driver_unix_convert(conn,new_name,&st);
1862 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1863 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1864 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1865 new_name, old_name));
1866 *perr = WERR_ACCESS_DENIED;
1873 if (driver->helpfile && strlen(driver->helpfile)) {
1874 if (!strequal(driver->helpfile, driver->driverpath) &&
1875 !strequal(driver->helpfile, driver->datafile) &&
1876 !strequal(driver->helpfile, driver->configfile)) {
1877 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1878 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1879 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1880 driver_unix_convert(conn,new_name,&st);
1881 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1882 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1883 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1884 new_name, old_name));
1885 *perr = WERR_ACCESS_DENIED;
1892 if (driver->dependentfiles) {
1893 for (i=0; *driver->dependentfiles[i]; i++) {
1894 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1895 !strequal(driver->dependentfiles[i], driver->datafile) &&
1896 !strequal(driver->dependentfiles[i], driver->configfile) &&
1897 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1899 for (j=0; j < i; j++) {
1900 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1905 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1906 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1907 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1908 driver_unix_convert(conn,new_name,&st);
1909 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
1910 OPENX_FILE_EXISTS_TRUNCATE|
1911 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1912 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1913 new_name, old_name));
1914 *perr = WERR_ACCESS_DENIED;
1923 close_cnum(conn, user->vuid);
1926 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1929 /****************************************************************************
1930 ****************************************************************************/
1931 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1934 const char *architecture;
1942 architecture = get_short_archi(driver->environment);
1943 if (!architecture) {
1947 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1948 * \\server is added in the rpc server layer.
1949 * It does make sense to NOT store the server's name in the printer TDB.
1952 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1954 /* .inf files do not always list a file for each of the four standard files.
1955 * Don't prepend a path to a null filename, or client claims:
1956 * "The server on which the printer resides does not have a suitable
1957 * <printer driver name> printer driver installed. Click OK if you
1958 * wish to install the driver on your local machine."
1960 if (strlen(driver->driverpath)) {
1961 fstrcpy(temp_name, driver->driverpath);
1962 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1965 if (strlen(driver->datafile)) {
1966 fstrcpy(temp_name, driver->datafile);
1967 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1970 if (strlen(driver->configfile)) {
1971 fstrcpy(temp_name, driver->configfile);
1972 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1975 if (strlen(driver->helpfile)) {
1976 fstrcpy(temp_name, driver->helpfile);
1977 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1980 if (driver->dependentfiles) {
1981 for (i=0; *driver->dependentfiles[i]; i++) {
1982 fstrcpy(temp_name, driver->dependentfiles[i]);
1983 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1987 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1989 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1996 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1999 driver->environment,
2004 driver->monitorname,
2005 driver->defaultdatatype);
2007 if (driver->dependentfiles) {
2008 for (i=0; *driver->dependentfiles[i]; i++) {
2009 len += tdb_pack(buf+len, buflen-len, "f",
2010 driver->dependentfiles[i]);
2014 if (len != buflen) {
2015 buf = (uint8 *)SMB_REALLOC(buf, len);
2017 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2028 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2032 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2038 /****************************************************************************
2039 ****************************************************************************/
2040 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2042 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2045 info3.cversion = driver->version;
2046 fstrcpy(info3.name,driver->name);
2047 fstrcpy(info3.environment,driver->environment);
2048 fstrcpy(info3.driverpath,driver->driverpath);
2049 fstrcpy(info3.datafile,driver->datafile);
2050 fstrcpy(info3.configfile,driver->configfile);
2051 fstrcpy(info3.helpfile,driver->helpfile);
2052 fstrcpy(info3.monitorname,driver->monitorname);
2053 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2054 info3.dependentfiles = driver->dependentfiles;
2056 return add_a_printer_driver_3(&info3);
2060 /****************************************************************************
2061 ****************************************************************************/
2062 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2064 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2068 fstrcpy(info.name, driver);
2069 fstrcpy(info.defaultdatatype, "RAW");
2071 fstrcpy(info.driverpath, "");
2072 fstrcpy(info.datafile, "");
2073 fstrcpy(info.configfile, "");
2074 fstrcpy(info.helpfile, "");
2076 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2079 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2080 fstrcpy(info.dependentfiles[0], "");
2082 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2084 SAFE_FREE(info.dependentfiles);
2091 /****************************************************************************
2092 ****************************************************************************/
2093 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2095 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2097 const char *architecture;
2102 ZERO_STRUCT(driver);
2104 architecture = get_short_archi(arch);
2105 if ( !architecture ) {
2106 return WERR_UNKNOWN_PRINTER_DRIVER;
2109 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2111 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2114 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2116 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2118 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2120 return WERR_UNKNOWN_PRINTER_DRIVER;
2122 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2131 driver.defaultdatatype);
2134 while (len < dbuf.dsize) {
2135 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2136 if ( !driver.dependentfiles ) {
2137 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2141 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2142 &driver.dependentfiles[i]);
2146 if ( driver.dependentfiles )
2147 fstrcpy( driver.dependentfiles[i], "" );
2149 SAFE_FREE(dbuf.dptr);
2151 if (len != dbuf.dsize) {
2152 SAFE_FREE(driver.dependentfiles);
2154 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2157 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2159 SAFE_FREE(driver.dependentfiles);
2166 /****************************************************************************
2167 Debugging function, dump at level 6 the struct in the logs.
2168 ****************************************************************************/
2170 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2173 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2176 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2182 if (driver.info_3 == NULL)
2185 info3=driver.info_3;
2187 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2188 DEBUGADD(20,("name:[%s]\n", info3->name));
2189 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2190 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2191 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2192 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2193 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2194 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2195 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2197 for (i=0; info3->dependentfiles &&
2198 *info3->dependentfiles[i]; i++) {
2199 DEBUGADD(20,("dependentfile:[%s]\n",
2200 info3->dependentfiles[i]));
2207 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2215 /****************************************************************************
2216 ****************************************************************************/
2217 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2221 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2226 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2227 nt_devmode->devicename,
2228 nt_devmode->formname,
2230 nt_devmode->specversion,
2231 nt_devmode->driverversion,
2233 nt_devmode->driverextra,
2234 nt_devmode->orientation,
2235 nt_devmode->papersize,
2236 nt_devmode->paperlength,
2237 nt_devmode->paperwidth,
2240 nt_devmode->defaultsource,
2241 nt_devmode->printquality,
2244 nt_devmode->yresolution,
2245 nt_devmode->ttoption,
2246 nt_devmode->collate,
2247 nt_devmode->logpixels,
2250 nt_devmode->bitsperpel,
2251 nt_devmode->pelswidth,
2252 nt_devmode->pelsheight,
2253 nt_devmode->displayflags,
2254 nt_devmode->displayfrequency,
2255 nt_devmode->icmmethod,
2256 nt_devmode->icmintent,
2257 nt_devmode->mediatype,
2258 nt_devmode->dithertype,
2259 nt_devmode->reserved1,
2260 nt_devmode->reserved2,
2261 nt_devmode->panningwidth,
2262 nt_devmode->panningheight,
2263 nt_devmode->nt_dev_private);
2266 if (nt_devmode->nt_dev_private) {
2267 len += tdb_pack(buf+len, buflen-len, "B",
2268 nt_devmode->driverextra,
2269 nt_devmode->nt_dev_private);
2272 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2277 /****************************************************************************
2278 Pack all values in all printer keys
2279 ***************************************************************************/
2281 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2285 REGISTRY_VALUE *val;
2286 REGVAL_CTR *val_ctr;
2293 /* loop over all keys */
2295 for ( i=0; i<data->num_keys; i++ ) {
2296 val_ctr = data->keys[i].values;
2297 num_values = regval_ctr_numvals( val_ctr );
2299 /* pack the keyname followed by a empty value */
2301 len += tdb_pack(buf+len, buflen-len, "pPdB",
2302 &data->keys[i].name,
2308 /* now loop over all values */
2310 for ( j=0; j<num_values; j++ ) {
2311 /* pathname should be stored as <key>\<value> */
2313 val = regval_ctr_specific_value( val_ctr, j );
2314 pstrcpy( path, data->keys[i].name );
2315 pstrcat( path, "\\" );
2316 pstrcat( path, regval_name(val) );
2318 len += tdb_pack(buf+len, buflen-len, "pPdB",
2323 regval_data_p(val) );
2325 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2332 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2338 /****************************************************************************
2339 Delete a printer - this just deletes the printer info file, any open
2340 handles are not affected.
2341 ****************************************************************************/
2343 uint32 del_a_printer(const char *sharename)
2346 pstring printdb_path;
2348 kbuf = make_printer_tdbkey( sharename );
2349 tdb_delete(tdb_printers, kbuf);
2351 kbuf= make_printers_secdesc_tdbkey( sharename );
2352 tdb_delete(tdb_printers, kbuf);
2354 close_all_print_db();
2356 if (geteuid() == 0) {
2357 pstrcpy(printdb_path, lock_path("printing/"));
2358 pstrcat(printdb_path, sharename);
2359 pstrcat(printdb_path, ".tdb");
2361 unlink(printdb_path);
2367 /****************************************************************************
2368 ****************************************************************************/
2369 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2374 TDB_DATA kbuf, dbuf;
2377 * in addprinter: no servername and the printer is the name
2378 * in setprinter: servername is \\server
2379 * and printer is \\server\\printer
2381 * Samba manages only local printers.
2382 * we currently don't support things like i
2383 * path=\\other_server\printer
2385 * We only store the printername, not \\server\printername
2388 if ( info->servername[0] != '\0' ) {
2389 trim_string(info->printername, info->servername, NULL);
2390 trim_char(info->printername, '\\', '\0');
2391 info->servername[0]='\0';
2395 * JFM: one day I'll forget.
2396 * below that's info->portname because that's the SAMBA sharename
2397 * and I made NT 'thinks' it's the portname
2398 * the info->sharename is the thing you can name when you add a printer
2399 * that's the short-name when you create shared printer for 95/98
2400 * So I've made a limitation in SAMBA: you can only have 1 printer model
2401 * behind a SAMBA share.
2409 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2412 info->default_priority,
2429 info->printprocessor,
2433 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2435 len += pack_values( info->data, buf+len, buflen-len );
2437 if (buflen != len) {
2438 buf = (uint8 *)SMB_REALLOC(buf, len);
2440 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2449 kbuf = make_printer_tdbkey( info->sharename );
2454 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2457 if (!W_ERROR_IS_OK(ret))
2458 DEBUG(8, ("error updating printer to tdb on disk\n"));
2462 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2463 info->sharename, info->drivername, info->portname, len));
2469 /****************************************************************************
2470 Malloc and return an NT devicemode.
2471 ****************************************************************************/
2473 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2476 char adevice[MAXDEVICENAME];
2477 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2479 if (nt_devmode == NULL) {
2480 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2484 ZERO_STRUCTP(nt_devmode);
2486 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2487 fstrcpy(nt_devmode->devicename, adevice);
2489 fstrcpy(nt_devmode->formname, "Letter");
2491 nt_devmode->specversion = 0x0401;
2492 nt_devmode->driverversion = 0x0400;
2493 nt_devmode->size = 0x00DC;
2494 nt_devmode->driverextra = 0x0000;
2495 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2496 DEFAULTSOURCE | COPIES | SCALE |
2497 PAPERSIZE | ORIENTATION;
2498 nt_devmode->orientation = 1;
2499 nt_devmode->papersize = PAPER_LETTER;
2500 nt_devmode->paperlength = 0;
2501 nt_devmode->paperwidth = 0;
2502 nt_devmode->scale = 0x64;
2503 nt_devmode->copies = 1;
2504 nt_devmode->defaultsource = BIN_FORMSOURCE;
2505 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2506 nt_devmode->color = COLOR_MONOCHROME;
2507 nt_devmode->duplex = DUP_SIMPLEX;
2508 nt_devmode->yresolution = 0;
2509 nt_devmode->ttoption = TT_SUBDEV;
2510 nt_devmode->collate = COLLATE_FALSE;
2511 nt_devmode->icmmethod = 0;
2512 nt_devmode->icmintent = 0;
2513 nt_devmode->mediatype = 0;
2514 nt_devmode->dithertype = 0;
2516 /* non utilisés par un driver d'imprimante */
2517 nt_devmode->logpixels = 0;
2518 nt_devmode->bitsperpel = 0;
2519 nt_devmode->pelswidth = 0;
2520 nt_devmode->pelsheight = 0;
2521 nt_devmode->displayflags = 0;
2522 nt_devmode->displayfrequency = 0;
2523 nt_devmode->reserved1 = 0;
2524 nt_devmode->reserved2 = 0;
2525 nt_devmode->panningwidth = 0;
2526 nt_devmode->panningheight = 0;
2528 nt_devmode->nt_dev_private = NULL;
2532 /****************************************************************************
2533 Deepcopy an NT devicemode.
2534 ****************************************************************************/
2536 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2538 NT_DEVICEMODE *new_nt_devicemode = NULL;
2540 if ( !nt_devicemode )
2543 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2544 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2548 new_nt_devicemode->nt_dev_private = NULL;
2549 if (nt_devicemode->nt_dev_private != NULL) {
2550 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2551 SAFE_FREE(new_nt_devicemode);
2552 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2557 return new_nt_devicemode;
2560 /****************************************************************************
2561 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2562 ****************************************************************************/
2564 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2566 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2568 if(nt_devmode == NULL)
2571 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2573 SAFE_FREE(nt_devmode->nt_dev_private);
2574 SAFE_FREE(*devmode_ptr);
2577 /****************************************************************************
2578 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2579 ****************************************************************************/
2581 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2583 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2588 free_nt_devicemode(&info->devmode);
2590 TALLOC_FREE( *info_ptr );
2594 /****************************************************************************
2595 ****************************************************************************/
2596 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2600 NT_DEVICEMODE devmode;
2602 ZERO_STRUCT(devmode);
2604 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2606 if (!*nt_devmode) return len;
2608 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2612 &devmode.specversion,
2613 &devmode.driverversion,
2615 &devmode.driverextra,
2616 &devmode.orientation,
2618 &devmode.paperlength,
2619 &devmode.paperwidth,
2622 &devmode.defaultsource,
2623 &devmode.printquality,
2626 &devmode.yresolution,
2632 &devmode.bitsperpel,
2634 &devmode.pelsheight,
2635 &devmode.displayflags,
2636 &devmode.displayfrequency,
2640 &devmode.dithertype,
2643 &devmode.panningwidth,
2644 &devmode.panningheight,
2645 &devmode.nt_dev_private);
2647 if (devmode.nt_dev_private) {
2648 /* the len in tdb_unpack is an int value and
2649 * devmode.driverextra is only a short
2651 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2652 devmode.driverextra=(uint16)extra_len;
2654 /* check to catch an invalid TDB entry so we don't segfault */
2655 if (devmode.driverextra == 0) {
2656 devmode.nt_dev_private = NULL;
2660 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2662 SAFE_FREE(devmode.nt_dev_private);
2666 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2667 if (devmode.nt_dev_private)
2668 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2673 /****************************************************************************
2674 Allocate and initialize a new slot.
2675 ***************************************************************************/
2677 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2682 if ( !name || !data )
2685 /* allocate another slot in the NT_PRINTER_KEY array */
2687 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2688 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2694 key_index = data->num_keys;
2696 /* initialze new key */
2698 data->keys[key_index].name = talloc_strdup( data, name );
2700 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2705 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2710 /****************************************************************************
2711 search for a registry key name in the existing printer data
2712 ***************************************************************************/
2714 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2718 for ( i=0; i<data->num_keys; i++ ) {
2719 if ( strequal( data->keys[i].name, name ) ) {
2721 /* cleanup memory */
2723 TALLOC_FREE( data->keys[i].name );
2724 TALLOC_FREE( data->keys[i].values );
2726 /* if not the end of the array, move remaining elements down one slot */
2729 if ( data->num_keys && (i < data->num_keys) )
2730 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2737 return data->num_keys;
2740 /****************************************************************************
2741 search for a registry key name in the existing printer data
2742 ***************************************************************************/
2744 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2749 if ( !data || !name )
2752 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2754 /* loop over all existing keys */
2756 for ( i=0; i<data->num_keys; i++ ) {
2757 if ( strequal(data->keys[i].name, name) ) {
2758 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2768 /****************************************************************************
2769 ***************************************************************************/
2771 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2775 int num_subkeys = 0;
2777 fstring *subkeys_ptr = NULL;
2788 /* special case of asking for the top level printer data registry key names */
2790 if ( strlen(key) == 0 ) {
2791 for ( i=0; i<data->num_keys; i++ ) {
2793 /* found a match, so allocate space and copy the name */
2795 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2796 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2801 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2808 /* asking for the subkeys of some key */
2809 /* subkey paths are stored in the key name using '\' as the delimiter */
2811 for ( i=0; i<data->num_keys; i++ ) {
2812 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2814 /* if we found the exact key, then break */
2815 key_len = strlen( key );
2816 if ( strlen(data->keys[i].name) == key_len )
2819 /* get subkey path */
2821 p = data->keys[i].name + key_len;
2824 fstrcpy( subkeyname, p );
2825 if ( (p = strchr( subkeyname, '\\' )) )
2828 /* don't add a key more than once */
2830 for ( j=0; j<num_subkeys; j++ ) {
2831 if ( strequal( subkeys_ptr[j], subkeyname ) )
2835 if ( j != num_subkeys )
2838 /* found a match, so allocate space and copy the name */
2840 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2841 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2846 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2852 /* return error if the key was not found */
2854 if ( i == data->num_keys ) {
2855 SAFE_FREE(subkeys_ptr);
2860 /* tag off the end */
2863 fstrcpy(subkeys_ptr[num_subkeys], "" );
2865 *subkeys = subkeys_ptr;
2871 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2874 smb_ucs2_t conv_str[1024];
2877 regval_ctr_delvalue(ctr, val_name);
2878 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2879 STR_TERMINATE | STR_NOALIGN);
2880 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2881 (char *) conv_str, str_size);
2884 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2887 regval_ctr_delvalue(ctr, val_name);
2888 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2889 (char *) &dword, sizeof(dword));
2892 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2895 uint8 bin_bool = (b ? 1 : 0);
2896 regval_ctr_delvalue(ctr, val_name);
2897 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2898 (char *) &bin_bool, sizeof(bin_bool));
2901 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2902 const char *multi_sz)
2904 smb_ucs2_t *conv_strs = NULL;
2907 /* a multi-sz has to have a null string terminator, i.e., the last
2908 string must be followed by two nulls */
2909 str_size = strlen(multi_sz) + 2;
2910 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2915 /* Change to byte units. */
2916 str_size *= sizeof(smb_ucs2_t);
2917 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2918 STR_TERMINATE | STR_NOALIGN);
2920 regval_ctr_delvalue(ctr, val_name);
2921 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2922 (char *) conv_strs, str_size);
2923 safe_free(conv_strs);
2927 /****************************************************************************
2928 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2930 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2931 * @return BOOL indicating success or failure
2932 ***************************************************************************/
2934 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2936 REGVAL_CTR *ctr = NULL;
2939 char *allocated_string = NULL;
2940 const char *ascii_str;
2943 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2944 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2945 ctr = info2->data->keys[i].values;
2947 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2948 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2950 /* we make the assumption that the netbios name is the same
2951 as the DNS name sinc ethe former will be what we used to
2954 if ( get_mydnsdomname( dnssuffix ) )
2955 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2957 fstrcpy( longname, global_myname() );
2959 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2961 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2962 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2963 SAFE_FREE(allocated_string);
2965 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2966 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2967 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2968 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2969 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2970 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2971 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2972 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2973 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2975 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2976 (info2->attributes &
2977 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2979 switch (info2->attributes & 0x3) {
2981 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2984 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2987 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2990 ascii_str = "unknown";
2992 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2997 /*****************************************************************
2998 ****************************************************************/
3000 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3004 REGVAL_CTR *ctr=NULL;
3005 UNISTR2 unistr_guid;
3007 /* find the DsSpooler key */
3008 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3009 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3010 ctr = info2->data->keys[i].values;
3012 regval_ctr_delvalue(ctr, "objectGUID");
3014 /* We used to store this as a REG_BINARY but that causes
3017 ZERO_STRUCT( unistr_guid );
3018 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3019 UNI_STR_TERMINATE );
3021 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3022 (char *)unistr_guid.buffer,
3023 unistr_guid.uni_max_len*2);
3027 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3028 NT_PRINTER_INFO_LEVEL *printer)
3032 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3033 char *srv_dn_utf8, **srv_cn_utf8;
3036 const char *attrs[] = {"objectGUID", NULL};
3038 WERROR win_rc = WERR_OK;
3040 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3042 /* figure out where to publish */
3043 ads_find_machine_acct(ads, &res, global_myname());
3045 /* We use ldap_get_dn here as we need the answer
3046 * in utf8 to call ldap_explode_dn(). JRA. */
3048 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3051 return WERR_SERVER_UNAVAILABLE;
3053 ads_msgfree(ads, res);
3054 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3056 ldap_memfree(srv_dn_utf8);
3058 return WERR_SERVER_UNAVAILABLE;
3060 /* Now convert to CH_UNIX. */
3061 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3062 ldap_memfree(srv_dn_utf8);
3063 ldap_memfree(srv_cn_utf8);
3065 return WERR_SERVER_UNAVAILABLE;
3067 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3068 ldap_memfree(srv_dn_utf8);
3069 ldap_memfree(srv_cn_utf8);
3072 return WERR_SERVER_UNAVAILABLE;
3075 ldap_memfree(srv_dn_utf8);
3076 ldap_memfree(srv_cn_utf8);
3078 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3079 if (!srv_cn_escaped) {
3080 SAFE_FREE(srv_cn_0);
3081 ldap_memfree(srv_dn_utf8);
3083 return WERR_SERVER_UNAVAILABLE;
3085 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3086 if (!sharename_escaped) {
3087 SAFE_FREE(srv_cn_escaped);
3088 SAFE_FREE(srv_cn_0);
3089 ldap_memfree(srv_dn_utf8);
3091 return WERR_SERVER_UNAVAILABLE;
3095 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3098 SAFE_FREE(srv_cn_0);
3099 SAFE_FREE(srv_cn_escaped);
3100 SAFE_FREE(sharename_escaped);
3102 /* build the ads mods */
3103 ctx = talloc_init("nt_printer_publish_ads");
3109 mods = ads_init_mods(ctx);
3113 talloc_destroy(ctx);
3117 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3118 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3119 printer->info_2->sharename);
3122 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3123 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3124 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3126 if (!ADS_ERR_OK(ads_rc))
3127 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3129 talloc_destroy(ctx);
3131 /* retreive the guid and store it locally */
3132 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3134 ads_pull_guid(ads, res, &guid);
3135 ads_msgfree(ads, res);
3136 store_printer_guid(printer->info_2, guid);
3137 win_rc = mod_a_printer(printer, 2);
3144 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3145 NT_PRINTER_INFO_LEVEL *printer)
3149 char *prt_dn = NULL;
3151 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3153 /* remove the printer from the directory */
3154 ads_rc = ads_find_printer_on_server(ads, &res,
3155 printer->info_2->sharename, global_myname());
3157 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3158 prt_dn = ads_get_dn(ads, res);
3160 ads_msgfree(ads, res);
3163 ads_rc = ads_del_dn(ads, prt_dn);
3164 ads_memfree(ads, prt_dn);
3167 ads_msgfree(ads, res);
3171 /****************************************************************************
3172 * Publish a printer in the directory
3174 * @param snum describing printer service
3175 * @return WERROR indicating status of publishing
3176 ***************************************************************************/
3178 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3181 ADS_STRUCT *ads = NULL;
3182 NT_PRINTER_INFO_LEVEL *printer = NULL;
3185 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3186 if (!W_ERROR_IS_OK(win_rc))
3190 case SPOOL_DS_PUBLISH:
3191 case SPOOL_DS_UPDATE:
3192 /* set the DsSpooler info and attributes */
3193 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3194 win_rc = WERR_NOMEM;
3198 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3200 case SPOOL_DS_UNPUBLISH:
3201 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3204 win_rc = WERR_NOT_SUPPORTED;
3208 win_rc = mod_a_printer(printer, 2);
3209 if (!W_ERROR_IS_OK(win_rc)) {
3210 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3214 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3216 DEBUG(3, ("ads_init() failed\n"));
3217 win_rc = WERR_SERVER_UNAVAILABLE;
3220 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3221 SAFE_FREE(ads->auth.password);
3222 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3225 /* ads_connect() will find the DC for us */
3226 ads_rc = ads_connect(ads);
3227 if (!ADS_ERR_OK(ads_rc)) {
3228 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3229 win_rc = WERR_ACCESS_DENIED;
3234 case SPOOL_DS_PUBLISH:
3235 case SPOOL_DS_UPDATE:
3236 win_rc = nt_printer_publish_ads(ads, printer);
3238 case SPOOL_DS_UNPUBLISH:
3239 win_rc = nt_printer_unpublish_ads(ads, printer);
3244 free_a_printer(&printer, 2);
3249 WERROR check_published_printers(void)
3252 ADS_STRUCT *ads = NULL;
3254 int n_services = lp_numservices();
3255 NT_PRINTER_INFO_LEVEL *printer = NULL;
3257 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3259 DEBUG(3, ("ads_init() failed\n"));
3260 return WERR_SERVER_UNAVAILABLE;
3262 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3263 SAFE_FREE(ads->auth.password);
3264 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3267 /* ads_connect() will find the DC for us */
3268 ads_rc = ads_connect(ads);
3269 if (!ADS_ERR_OK(ads_rc)) {
3270 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3272 ads_kdestroy("MEMORY:prtpub_cache");
3273 return WERR_ACCESS_DENIED;
3276 for (snum = 0; snum < n_services; snum++) {
3277 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3280 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3281 lp_servicename(snum))) &&
3282 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3283 nt_printer_publish_ads(ads, printer);
3285 free_a_printer(&printer, 2);
3289 ads_kdestroy("MEMORY:prtpub_cache");
3293 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3296 NT_PRINTER_INFO_LEVEL *printer = NULL;
3298 REGISTRY_VALUE *guid_val;
3303 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3305 if (!W_ERROR_IS_OK(win_rc) ||
3306 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3307 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3308 !(ctr = printer->info_2->data->keys[i].values) ||
3309 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3311 free_a_printer(&printer, 2);
3315 /* fetching printer guids really ought to be a separate function. */
3320 /* We used to store the guid as REG_BINARY, then swapped
3321 to REG_SZ for Vista compatibility so check for both */
3323 switch ( regval_type(guid_val) ){
3325 rpcstr_pull( guid_str, regval_data_p(guid_val),
3326 sizeof(guid_str)-1, -1, STR_TERMINATE );
3327 ret = smb_string_to_uuid( guid_str, guid );
3330 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3334 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3337 DEBUG(0,("is_printer_published: GUID value stored as "
3338 "invaluid type (%d)\n", regval_type(guid_val) ));
3343 free_a_printer(&printer, 2);
3347 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3352 WERROR check_published_printers(void)
3357 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3362 #endif /* HAVE_ADS */
3364 /****************************************************************************
3365 ***************************************************************************/
3367 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3369 NT_PRINTER_DATA *data;
3371 int removed_keys = 0;
3375 empty_slot = data->num_keys;
3378 return WERR_INVALID_PARAM;
3380 /* remove all keys */
3382 if ( !strlen(key) ) {
3384 TALLOC_FREE( data );
3388 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3394 /* remove a specific key (and all subkeys) */
3396 for ( i=0; i<data->num_keys; i++ ) {
3397 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3398 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3399 data->keys[i].name));
3401 TALLOC_FREE( data->keys[i].name );
3402 TALLOC_FREE( data->keys[i].values );
3404 /* mark the slot as empty */
3406 ZERO_STRUCTP( &data->keys[i] );
3410 /* find the first empty slot */
3412 for ( i=0; i<data->num_keys; i++ ) {
3413 if ( !data->keys[i].name ) {
3420 if ( i == data->num_keys )
3421 /* nothing was removed */
3422 return WERR_INVALID_PARAM;
3424 /* move everything down */
3426 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3427 if ( data->keys[i].name ) {
3428 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3429 ZERO_STRUCTP( &data->keys[i] );
3437 data->num_keys -= removed_keys;
3439 /* sanity check to see if anything is left */
3441 if ( !data->num_keys ) {
3442 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3444 SAFE_FREE( data->keys );
3445 ZERO_STRUCTP( data );
3451 /****************************************************************************
3452 ***************************************************************************/
3454 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3456 WERROR result = WERR_OK;
3459 /* we must have names on non-zero length */
3461 if ( !key || !*key|| !value || !*value )
3462 return WERR_INVALID_NAME;
3464 /* find the printer key first */
3466 key_index = lookup_printerkey( p2->data, key );
3467 if ( key_index == -1 )
3470 /* make sure the value exists so we can return the correct error code */
3472 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3473 return WERR_BADFILE;
3475 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3477 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3483 /****************************************************************************
3484 ***************************************************************************/
3486 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3487 uint32 type, uint8 *data, int real_len )
3489 WERROR result = WERR_OK;
3492 /* we must have names on non-zero length */
3494 if ( !key || !*key|| !value || !*value )
3495 return WERR_INVALID_NAME;
3497 /* find the printer key first */
3499 key_index = lookup_printerkey( p2->data, key );
3500 if ( key_index == -1 )
3501 key_index = add_new_printer_key( p2->data, key );
3503 if ( key_index == -1 )
3506 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3507 type, (const char *)data, real_len );
3509 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3510 key, value, type, real_len ));
3515 /****************************************************************************
3516 ***************************************************************************/
3518 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3522 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3525 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3528 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3531 /****************************************************************************
3532 Unpack a list of registry values frem the TDB
3533 ***************************************************************************/
3535 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3539 pstring string, valuename, keyname;
3543 REGISTRY_VALUE *regval_p;
3546 /* add the "PrinterDriverData" key first for performance reasons */
3548 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3550 /* loop and unpack the rest of the registry values */
3554 /* check to see if there are any more registry values */
3557 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3561 /* unpack the next regval */
3563 len += tdb_unpack(buf+len, buflen-len, "fdB",
3569 /* lookup for subkey names which have a type of REG_NONE */
3570 /* there's no data with this entry */
3572 if ( type == REG_NONE ) {
3573 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3574 add_new_printer_key( printer_data, string );
3579 * break of the keyname from the value name.
3580 * Valuenames can have embedded '\'s so be careful.
3581 * only support one level of keys. See the
3582 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3586 str = strchr_m( string, '\\');
3588 /* Put in "PrinterDriverData" is no key specified */
3591 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3592 pstrcpy( valuename, string );
3596 pstrcpy( keyname, string );
3597 pstrcpy( valuename, str+1 );
3600 /* see if we need a new key */
3602 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3603 key_index = add_new_printer_key( printer_data, keyname );
3605 if ( key_index == -1 ) {
3606 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3611 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3613 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3614 Thanks to Martin Zielinski for the hint. */
3616 if ( type == REG_BINARY &&
3617 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3618 strequal( valuename, "objectGUID" ) )
3621 UNISTR2 unistr_guid;
3623 ZERO_STRUCT( unistr_guid );
3625 /* convert the GUID to a UNICODE string */
3627 memcpy( &guid, data_p, sizeof(struct GUID) );
3629 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3630 UNI_STR_TERMINATE );
3632 regval_ctr_addvalue( printer_data->keys[key_index].values,
3634 (const char *)unistr_guid.buffer,
3635 unistr_guid.uni_str_len*2 );
3640 regval_ctr_addvalue( printer_data->keys[key_index].values,
3641 valuename, type, (const char *)data_p,
3646 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3653 /****************************************************************************
3654 ***************************************************************************/
3656 static void map_to_os2_driver(fstring drivername)
3658 static BOOL initialised=False;
3659 static fstring last_from,last_to;
3660 char *mapfile = lp_os2_driver_map();
3661 char **lines = NULL;
3665 if (!strlen(drivername))
3672 *last_from = *last_to = 0;
3676 if (strequal(drivername,last_from)) {
3677 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3678 fstrcpy(drivername,last_to);
3682 lines = file_lines_load(mapfile, &numlines,0);
3683 if (numlines == 0 || lines == NULL) {
3684 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3689 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3691 for( i = 0; i < numlines; i++) {
3692 char *nt_name = lines[i];
3693 char *os2_name = strchr(nt_name,'=');
3700 while (isspace(*nt_name))
3703 if (!*nt_name || strchr("#;",*nt_name))
3707 int l = strlen(nt_name);
3708 while (l && isspace(nt_name[l-1])) {
3714 while (isspace(*os2_name))
3718 int l = strlen(os2_name);
3719 while (l && isspace(os2_name[l-1])) {
3725 if (strequal(nt_name,drivername)) {
3726 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3727 fstrcpy(last_from,drivername);
3728 fstrcpy(last_to,os2_name);
3729 fstrcpy(drivername,os2_name);
3730 file_lines_free(lines);
3735 file_lines_free(lines);
3738 /****************************************************************************
3739 Get a default printer info 2 struct.
3740 ****************************************************************************/
3741 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3743 int snum = lp_servicenumber(sharename);
3745 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3746 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3747 servername, sharename);
3748 fstrcpy(info->sharename, sharename);
3749 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3751 /* by setting the driver name to an empty string, a local NT admin
3752 can now run the **local** APW to install a local printer driver
3753 for a Samba shared printer in 2.2. Without this, drivers **must** be
3754 installed on the Samba server for NT clients --jerry */
3755 #if 0 /* JERRY --do not uncomment-- */
3756 if (!*info->drivername)
3757 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3761 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3763 pstrcpy(info->comment, "");
3764 fstrcpy(info->printprocessor, "winprint");
3765 fstrcpy(info->datatype, "RAW");
3768 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3769 /* Pull the location and comment strings from cups if we don't
3771 if ( !strlen(info->location) || !strlen(info->comment) )
3772 cups_pull_comment_location( info );
3776 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3778 info->starttime = 0; /* Minutes since 12:00am GMT */
3779 info->untiltime = 0; /* Minutes since 12:00am GMT */
3781 info->default_priority = 1;
3782 info->setuptime = (uint32)time(NULL);
3785 * I changed this as I think it is better to have a generic
3786 * DEVMODE than to crash Win2k explorer.exe --jerry
3787 * See the HP Deskjet 990c Win2k drivers for an example.
3789 * However the default devmode appears to cause problems
3790 * with the HP CLJ 8500 PCL driver. Hence the addition of
3791 * the "default devmode" parameter --jerry 22/01/2002
3794 if (lp_default_devmode(snum)) {
3795 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3799 info->devmode = NULL;
3802 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3810 free_nt_devicemode(&info->devmode);
3812 return WERR_ACCESS_DENIED;
3815 /****************************************************************************
3816 ****************************************************************************/
3817 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3820 int snum = lp_servicenumber(sharename);
3821 TDB_DATA kbuf, dbuf;
3822 fstring printername;
3823 char adevice[MAXDEVICENAME];
3825 kbuf = make_printer_tdbkey( sharename );
3827 dbuf = tdb_fetch(tdb_printers, kbuf);
3829 return get_a_printer_2_default(info, servername, sharename);
3832 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3835 &info->default_priority,
3842 &info->c_setprinter,
3852 info->printprocessor,
3856 /* Samba has to have shared raw drivers. */
3857 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3858 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3860 /* Restore the stripped strings. */
3861 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3863 if ( lp_force_printername(snum) ) {
3864 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3866 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3869 fstrcpy(info->printername, printername);
3872 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3873 /* Pull the location and comment strings from cups if we don't
3875 if ( !strlen(info->location) || !strlen(info->comment) )
3876 cups_pull_comment_location( info );
3880 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3883 * Some client drivers freak out if there is a NULL devmode
3884 * (probably the driver is not checking before accessing
3885 * the devmode pointer) --jerry
3887 * See comments in get_a_printer_2_default()
3890 if (lp_default_devmode(snum) && !info->devmode) {
3891 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3893 info->devmode = construct_nt_devicemode(printername);
3896 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3897 if (info->devmode) {
3898 fstrcpy(info->devmode->devicename, adevice);
3901 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3902 DEBUG(0,("unpack_values: talloc() failed!\n"));
3903 SAFE_FREE(dbuf.dptr);
3906 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3908 /* This will get the current RPC talloc context, but we should be
3909 passing this as a parameter... fixme... JRA ! */
3911 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3912 SAFE_FREE(dbuf.dptr);
3916 /* Fix for OS/2 drivers. */
3918 if (get_remote_arch() == RA_OS2) {
3919 map_to_os2_driver(info->drivername);
3922 SAFE_FREE(dbuf.dptr);
3924 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3925 sharename, info->printername, info->drivername));
3930 /****************************************************************************
3931 Debugging function, dump at level 6 the struct in the logs.
3932 ****************************************************************************/
3933 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3936 NT_PRINTER_INFO_LEVEL_2 *info2;
3938 DEBUG(106,("Dumping printer at level [%d]\n", level));
3943 if (printer->info_2 == NULL)
3947 info2=printer->info_2;
3949 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3950 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3951 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3952 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3953 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3954 DEBUGADD(106,("status:[%d]\n", info2->status));
3955 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3956 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3957 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3958 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3959 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3961 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3962 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3963 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3964 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3965 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3966 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3967 DEBUGADD(106,("location:[%s]\n", info2->location));
3968 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3969 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3970 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3971 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3977 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3985 /****************************************************************************
3986 Update the changeid time.
3987 This is SO NASTY as some drivers need this to change, others need it
3988 static. This value will change every second, and I must hope that this
3989 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3991 ****************************************************************************/
3993 static uint32 rev_changeid(void)
3997 get_process_uptime(&tv);
4000 /* Return changeid as msec since spooler restart */
4001 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4004 * This setting seems to work well but is too untested
4005 * to replace the above calculation. Left in for experiementation
4006 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4008 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4014 * The function below are the high level ones.
4015 * only those ones must be called from the spoolss code.
4019 /****************************************************************************
4020 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4021 ****************************************************************************/
4023 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4027 dump_a_printer(printer, level);
4033 * Update the changestamp. Emperical tests show that the
4034 * ChangeID is always updated,but c_setprinter is
4035 * global spooler variable (not per printer).
4038 /* ChangeID **must** be increasing over the lifetime
4039 of client's spoolss service in order for the
4040 client's cache to show updates */
4042 printer->info_2->changeid = rev_changeid();
4045 * Because one day someone will ask:
4046 * NT->NT An admin connection to a remote
4047 * printer show changes imeediately in
4048 * the properities dialog
4050 * A non-admin connection will only show the
4051 * changes after viewing the properites page
4052 * 2 times. Seems to be related to a
4053 * race condition in the client between the spooler
4054 * updating the local cache and the Explorer.exe GUI
4055 * actually displaying the properties.
4057 * This is fixed in Win2k. admin/non-admin
4058 * connections both display changes immediately.
4063 result=update_a_printer_2(printer->info_2);
4068 result=WERR_UNKNOWN_LEVEL;
4075 /****************************************************************************
4076 Initialize printer devmode & data with previously saved driver init values.
4077 ****************************************************************************/
4079 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4084 NT_PRINTER_INFO_LEVEL_2 info;
4090 * Delete any printer data 'values' already set. When called for driver
4091 * replace, there will generally be some, but during an add printer, there
4092 * should not be any (if there are delete them).
4095 if ( info_ptr->data )
4096 delete_all_printer_data( info_ptr, "" );
4098 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4100 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4103 * When changing to a driver that has no init info in the tdb, remove
4104 * the previous drivers init info and leave the new on blank.
4106 free_nt_devicemode(&info_ptr->devmode);
4111 * Get the saved DEVMODE..
4114 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4117 * The saved DEVMODE contains the devicename from the printer used during
4118 * the initialization save. Change it to reflect the new printer.
4121 if ( info.devmode ) {
4122 ZERO_STRUCT(info.devmode->devicename);
4123 fstrcpy(info.devmode->devicename, info_ptr->printername);
4127 * NT/2k does not change out the entire DeviceMode of a printer
4128 * when changing the driver. Only the driverextra, private, &
4129 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4131 * Later examination revealed that Windows NT/2k does reset the
4132 * the printer's device mode, bit **only** when you change a
4133 * property of the device mode such as the page orientation.
4138 /* Bind the saved DEVMODE to the new the printer */
4140 free_nt_devicemode(&info_ptr->devmode);
4141 info_ptr->devmode = info.devmode;
4143 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4144 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4146 /* Add the printer data 'values' to the new printer */
4148 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4149 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4153 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4156 SAFE_FREE(dbuf.dptr);
4161 /****************************************************************************
4162 Initialize printer devmode & data with previously saved driver init values.
4163 When a printer is created using AddPrinter, the drivername bound to the
4164 printer is used to lookup previously saved driver initialization info, which
4165 is bound to the new printer.
4166 ****************************************************************************/
4168 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4170 BOOL result = False;
4174 result = set_driver_init_2(printer->info_2);
4178 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4186 /****************************************************************************
4187 Delete driver init data stored for a specified driver
4188 ****************************************************************************/
4190 BOOL del_driver_init(char *drivername)
4194 if (!drivername || !*drivername) {
4195 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4199 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4201 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4203 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4206 /****************************************************************************
4207 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4208 in the tdb. Note: this is different from the driver entry and the printer
4209 entry. There should be a single driver init entry for each driver regardless
4210 of whether it was installed from NT or 2K. Technically, they should be
4211 different, but they work out to the same struct.
4212 ****************************************************************************/
4214 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4218 int buflen, len, ret;
4226 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4228 len += pack_values( info->data, buf+len, buflen-len );
4231 buf = (uint8 *)SMB_REALLOC(buf, len);
4233 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4241 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4246 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4250 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4254 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4255 info->sharename, info->drivername));
4260 /****************************************************************************
4261 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4262 ****************************************************************************/
4264 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4268 dump_a_printer(printer, level);
4272 result = update_driver_init_2(printer->info_2);
4282 /****************************************************************************
4283 Convert the printer data value, a REG_BINARY array, into an initialization
4284 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4285 got to keep the endians happy :).
4286 ****************************************************************************/
4288 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4290 BOOL result = False;
4294 ZERO_STRUCT(devmode);
4296 prs_init(&ps, 0, ctx, UNMARSHALL);
4297 ps.data_p = (char *)data;
4298 ps.buffer_size = data_len;
4300 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4301 result = convert_devicemode("", &devmode, &nt_devmode);
4303 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4308 /****************************************************************************
4309 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4311 1. Use the driver's config DLL to this UNC printername and:
4312 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4313 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4314 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4316 The last step triggers saving the "driver initialization" information for
4317 this printer into the tdb. Later, new printers that use this driver will
4318 have this initialization information bound to them. This simulates the
4319 driver initialization, as if it had run on the Samba server (as it would
4322 The Win32 client side code requirement sucks! But until we can run arbitrary
4323 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4325 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4326 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4327 about it and you will realize why. JRR 010720
4328 ****************************************************************************/
4330 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4332 WERROR status = WERR_OK;
4333 TALLOC_CTX *ctx = NULL;
4334 NT_DEVICEMODE *nt_devmode = NULL;
4335 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4338 * When the DEVMODE is already set on the printer, don't try to unpack it.
4340 DEBUG(8,("save_driver_init_2: Enter...\n"));
4342 if ( !printer->info_2->devmode && data_len ) {
4344 * Set devmode on printer info, so entire printer initialization can be
4348 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4351 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4352 status = WERR_NOMEM;
4356 ZERO_STRUCTP(nt_devmode);
4359 * The DEVMODE is held in the 'data' component of the param in raw binary.
4360 * Convert it to to a devmode structure
4362 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4363 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4364 status = WERR_INVALID_PARAM;
4368 printer->info_2->devmode = nt_devmode;
4372 * Pack up and add (or update) the DEVMODE and any current printer data to
4373 * a 'driver init' element in the tdb
4377 if ( update_driver_init(printer, 2) != 0 ) {
4378 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4379 status = WERR_NOMEM;
4384 * If driver initialization info was successfully saved, set the current
4385 * printer to match it. This allows initialization of the current printer
4386 * as well as the driver.
4388 status = mod_a_printer(printer, 2);
4389 if (!W_ERROR_IS_OK(status)) {
4390 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4391 printer->info_2->printername));
4395 talloc_destroy(ctx);
4396 free_nt_devicemode( &nt_devmode );
4398 printer->info_2->devmode = tmp_devmode;
4403 /****************************************************************************
4404 Update the driver init info (DEVMODE and specifics) for a printer
4405 ****************************************************************************/
4407 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4409 WERROR status = WERR_OK;
4413 status = save_driver_init_2( printer, data, data_len );
4416 status = WERR_UNKNOWN_LEVEL;
4423 /****************************************************************************
4424 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4426 Previously the code had a memory allocation problem because it always
4427 used the TALLOC_CTX from the Printer_entry*. This context lasts
4428 as a long as the original handle is open. So if the client made a lot
4429 of getprinter[data]() calls, the memory usage would climb. Now we use
4430 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4431 still use the Printer_entry->ctx for maintaining the cache copy though
4432 since that object must live as long as the handle by definition.
4435 ****************************************************************************/
4437 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4438 const char *sharename)
4443 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4445 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4446 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4452 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4453 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4454 TALLOC_FREE( *pp_printer );
4459 fstrcpy( servername, print_hnd->servername );
4461 fstrcpy( servername, "%L" );
4462 standard_sub_basic( "", "", servername,
4463 sizeof(servername)-1 );
4466 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4469 /* we have a new printer now. Save it with this handle */
4471 if ( !W_ERROR_IS_OK(result) ) {
4472 TALLOC_FREE( *pp_printer );
4473 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4474 sharename, (unsigned int)level, dos_errstr(result)));
4478 dump_a_printer( *pp_printer, level);
4483 TALLOC_FREE( *pp_printer );
4484 return WERR_UNKNOWN_LEVEL;
4490 /****************************************************************************
4491 Deletes a NT_PRINTER_INFO_LEVEL struct.
4492 ****************************************************************************/
4494 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4496 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4503 if ( printer->info_2 )
4504 free_nt_printer_info_level_2(&printer->info_2);
4508 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4512 TALLOC_FREE(*pp_printer);
4517 /****************************************************************************
4518 ****************************************************************************/
4519 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4522 DEBUG(104,("adding a printer at level [%d]\n", level));
4523 dump_a_printer_driver(driver, level);
4527 result=add_a_printer_driver_3(driver.info_3);
4531 result=add_a_printer_driver_6(driver.info_6);
4541 /****************************************************************************
4542 ****************************************************************************/
4544 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4545 fstring drivername, const char *architecture, uint32 version)
4551 /* Sometime we just want any version of the driver */
4553 if ( version == DRIVER_ANY_VERSION ) {
4554 /* look for Win2k first and then for NT4 */
4555 result = get_a_printer_driver_3(&driver->info_3, drivername,
4558 if ( !W_ERROR_IS_OK(result) ) {
4559 result = get_a_printer_driver_3( &driver->info_3,
4560 drivername, architecture, 2 );
4563 result = get_a_printer_driver_3(&driver->info_3, drivername,
4564 architecture, version);
4573 if (W_ERROR_IS_OK(result))
4574 dump_a_printer_driver(*driver, level);
4579 /****************************************************************************
4580 ****************************************************************************/
4581 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4588 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4589 if (driver.info_3 != NULL)
4591 info3=driver.info_3;
4592 SAFE_FREE(info3->dependentfiles);
4593 ZERO_STRUCTP(info3);
4603 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4604 if (driver.info_6 != NULL) {
4605 info6=driver.info_6;
4606 SAFE_FREE(info6->dependentfiles);
4607 SAFE_FREE(info6->previousnames);
4608 ZERO_STRUCTP(info6);
4624 /****************************************************************************
4625 Determine whether or not a particular driver is currently assigned
4627 ****************************************************************************/
4629 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4632 int n_services = lp_numservices();
4633 NT_PRINTER_INFO_LEVEL *printer = NULL;
4634 BOOL in_use = False;
4639 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4641 /* loop through the printers.tdb and check for the drivername */
4643 for (snum=0; snum<n_services && !in_use; snum++) {
4644 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4647 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4650 if ( strequal(info_3->name, printer->info_2->drivername) )
4653 free_a_printer( &printer, 2 );
4656 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4659 NT_PRINTER_DRIVER_INFO_LEVEL d;
4662 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4664 /* we can still remove the driver if there is one of
4665 "Windows NT x86" version 2 or 3 left */
4667 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4668 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4671 switch ( info_3->cversion ) {
4673 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4676 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4679 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4681 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4686 /* now check the error code */
4688 if ( W_ERROR_IS_OK(werr) ) {
4689 /* it's ok to remove the driver, we have other architctures left */
4691 free_a_printer_driver( d, 3 );
4695 /* report that the driver is not in use by default */
4701 /**********************************************************************
4702 Check to see if a ogiven file is in use by *info
4703 *********************************************************************/
4705 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4712 if ( strequal(file, info->driverpath) )
4715 if ( strequal(file, info->datafile) )
4718 if ( strequal(file, info->configfile) )
4721 if ( strequal(file, info->helpfile) )
4724 /* see of there are any dependent files to examine */
4726 if ( !info->dependentfiles )
4729 while ( *info->dependentfiles[i] ) {
4730 if ( strequal(file, info->dependentfiles[i]) )
4739 /**********************************************************************
4740 Utility function to remove the dependent file pointed to by the
4741 input parameter from the list
4742 *********************************************************************/
4744 static void trim_dependent_file( fstring files[], int idx )
4747 /* bump everything down a slot */
4749 while( *files[idx+1] ) {
4750 fstrcpy( files[idx], files[idx+1] );
4759 /**********************************************************************
4760 Check if any of the files used by src are also used by drv
4761 *********************************************************************/
4763 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4764 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4766 BOOL in_use = False;
4772 /* check each file. Remove it from the src structure if it overlaps */
4774 if ( drv_file_in_use(src->driverpath, drv) ) {
4776 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4777 fstrcpy( src->driverpath, "" );
4780 if ( drv_file_in_use(src->datafile, drv) ) {
4782 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4783 fstrcpy( src->datafile, "" );
4786 if ( drv_file_in_use(src->configfile, drv) ) {
4788 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4789 fstrcpy( src->configfile, "" );
4792 if ( drv_file_in_use(src->helpfile, drv) ) {
4794 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4795 fstrcpy( src->helpfile, "" );
4798 /* are there any dependentfiles to examine? */
4800 if ( !src->dependentfiles )
4803 while ( *src->dependentfiles[i] ) {
4804 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4806 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4807 trim_dependent_file( src->dependentfiles, i );
4815 /****************************************************************************
4816 Determine whether or not a particular driver files are currently being
4817 used by any other driver.
4819 Return value is True if any files were in use by other drivers
4820 and False otherwise.
4822 Upon return, *info has been modified to only contain the driver files
4823 which are not in use
4824 ****************************************************************************/
4826 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4831 fstring *list = NULL;
4832 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4837 version = info->cversion;
4839 /* loop over all driver versions */
4841 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4843 /* get the list of drivers */
4846 ndrivers = get_ntdrivers(&list, info->environment, version);
4848 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4849 ndrivers, info->environment, version));
4851 /* check each driver for overlap in files */
4853 for (i=0; i<ndrivers; i++) {
4854 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4856 ZERO_STRUCT(driver);
4858 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4863 /* check if d2 uses any files from d1 */
4864 /* only if this is a different driver than the one being deleted */
4866 if ( !strequal(info->name, driver.info_3->name) ) {
4867 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4868 free_a_printer_driver(driver, 3);
4874 free_a_printer_driver(driver, 3);
4879 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4881 driver.info_3 = info;
4883 if ( DEBUGLEVEL >= 20 )
4884 dump_a_printer_driver( driver, 3 );
4889 /****************************************************************************
4890 Actually delete the driver files. Make sure that
4891 printer_driver_files_in_use() return False before calling
4893 ****************************************************************************/
4895 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4900 connection_struct *conn;
4909 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4912 * Connect to the print$ share under the same account as the
4913 * user connected to the rpc pipe. Note we must be root to
4917 null_pw = data_blob_null;
4918 fstrcpy(res_type, "A:");
4920 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4924 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4928 if ( !CAN_WRITE(conn) ) {
4929 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4933 /* Save who we are - we are temporarily becoming the connection user. */
4935 if ( !become_user(conn, conn->vuid) ) {
4936 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4940 /* now delete the files; must strip the '\print$' string from
4943 if ( *info_3->driverpath ) {
4944 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4946 driver_unix_convert(conn,file,&st);
4947 DEBUG(10,("deleting driverfile [%s]\n", s));
4948 unlink_internals(conn, NULL, 0, file, False);
4952 if ( *info_3->configfile ) {
4953 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4955 driver_unix_convert(conn,file,&st);
4956 DEBUG(10,("deleting configfile [%s]\n", s));
4957 unlink_internals(conn, NULL, 0, file, False);
4961 if ( *info_3->datafile ) {
4962 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4964 driver_unix_convert(conn,file,&st);
4965 DEBUG(10,("deleting datafile [%s]\n", s));
4966 unlink_internals(conn, NULL, 0, file, False);
4970 if ( *info_3->helpfile ) {
4971 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4973 driver_unix_convert(conn,file,&st);
4974 DEBUG(10,("deleting helpfile [%s]\n", s));
4975 unlink_internals(conn, NULL, 0, file, False);
4979 /* check if we are done removing files */
4981 if ( info_3->dependentfiles ) {
4982 while ( info_3->dependentfiles[i][0] ) {
4985 /* bypass the "\print$" portion of the path */
4987 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4989 driver_unix_convert(conn,file,&st);
4990 DEBUG(10,("deleting dependent file [%s]\n", file));
4991 unlink_internals(conn, NULL, 0, file, False);
5003 /****************************************************************************
5004 Remove a printer driver from the TDB. This assumes that the the driver was
5005 previously looked up.
5006 ***************************************************************************/
5008 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5009 uint32 version, BOOL delete_files )
5014 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5016 /* delete the tdb data first */
5018 arch = get_short_archi(info_3->environment);
5020 return WERR_UNKNOWN_PRINTER_DRIVER;
5022 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5023 arch, version, info_3->name);
5025 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5026 key, delete_files ? "TRUE" : "FALSE" ));
5028 ctr.info_3 = info_3;
5029 dump_a_printer_driver( ctr, 3 );
5031 /* check if the driver actually exists for this environment */
5033 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5035 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5036 return WERR_UNKNOWN_PRINTER_DRIVER;
5039 SAFE_FREE( dbuf.dptr );
5041 /* ok... the driver exists so the delete should return success */
5043 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5044 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5045 return WERR_ACCESS_DENIED;
5049 * now delete any associated files if delete_files == True
5050 * even if this part failes, we return succes because the
5051 * driver doesn not exist any more
5055 delete_driver_files( info_3, user );
5058 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5063 /****************************************************************************
5064 Store a security desc for a printer.
5065 ****************************************************************************/
5067 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5069 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5070 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5072 TALLOC_CTX *mem_ctx = NULL;
5076 mem_ctx = talloc_init("nt_printing_setsec");
5077 if (mem_ctx == NULL)
5080 /* The old owner and group sids of the security descriptor are not
5081 present when new ACEs are added or removed by changing printer
5082 permissions through NT. If they are NULL in the new security
5083 descriptor then copy them over from the old one. */
5085 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5086 DOM_SID *owner_sid, *group_sid;
5087 SEC_ACL *dacl, *sacl;
5088 SEC_DESC *psd = NULL;
5091 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5092 status = WERR_NOMEM;
5096 /* Pick out correct owner and group sids */
5098 owner_sid = secdesc_ctr->sd->owner_sid ?
5099 secdesc_ctr->sd->owner_sid :
5100 old_secdesc_ctr->sd->owner_sid;
5102 group_sid = secdesc_ctr->sd->group_sid ?
5103 secdesc_ctr->sd->group_sid :
5104 old_secdesc_ctr->sd->group_sid;
5106 dacl = secdesc_ctr->sd->dacl ?
5107 secdesc_ctr->sd->dacl :
5108 old_secdesc_ctr->sd->dacl;
5110 sacl = secdesc_ctr->sd->sacl ?
5111 secdesc_ctr->sd->sacl :
5112 old_secdesc_ctr->sd->sacl;
5114 /* Make a deep copy of the security descriptor */
5116 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5117 owner_sid, group_sid,
5123 status = WERR_NOMEM;
5127 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5130 if (!new_secdesc_ctr) {
5131 new_secdesc_ctr = secdesc_ctr;
5134 /* Store the security descriptor in a tdb */
5136 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5137 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5139 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5141 status = WERR_BADFUNC;
5145 kbuf = make_printers_secdesc_tdbkey( sharename );
5147 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5150 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5151 status = WERR_BADFUNC;
5154 /* Free malloc'ed memory */
5160 talloc_destroy(mem_ctx);
5164 /****************************************************************************
5165 Construct a default security descriptor buffer for a printer.
5166 ****************************************************************************/
5168 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5170 SEC_ACE ace[5]; /* max number of ace entries */
5173 SEC_ACL *psa = NULL;
5174 SEC_DESC_BUF *sdb = NULL;
5175 SEC_DESC *psd = NULL;
5179 /* Create an ACE where Everyone is allowed to print */
5181 init_sec_access(&sa, PRINTER_ACE_PRINT);
5182 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5183 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5185 /* Add the domain admins group if we are a DC */
5188 DOM_SID domadmins_sid;
5190 sid_copy(&domadmins_sid, get_global_sam_sid());
5191 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5193 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5194 init_sec_ace(&ace[i++], &domadmins_sid,
5195 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5196 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5197 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5198 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5200 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5201 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5203 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5204 init_sec_ace(&ace[i++], &adm_sid,
5205 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5206 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5207 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5208 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5211 /* add BUILTIN\Administrators as FULL CONTROL */
5213 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5214 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5215 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5216 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5217 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5218 SEC_ACE_TYPE_ACCESS_ALLOWED,
5219 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5221 /* Make the security descriptor owned by the BUILTIN\Administrators */
5223 /* The ACL revision number in rpc_secdesc.h differs from the one
5224 created by NT when setting ACE entries in printer
5225 descriptors. NT4 complains about the property being edited by a
5228 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5229 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5230 &global_sid_Builtin_Administrators,
5231 &global_sid_Builtin_Administrators,
5232 NULL, psa, &sd_size);
5236 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5240 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5242 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5243 (unsigned int)sd_size));
5248 /****************************************************************************
5249 Get a security desc for a printer.
5250 ****************************************************************************/
5252 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5258 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5259 sharename = temp + 1;
5264 /* Fetch security descriptor from tdb */
5266 kbuf = make_printers_secdesc_tdbkey( sharename );
5268 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5269 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5273 DEBUG(4,("using default secdesc for %s\n", sharename));
5275 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5279 /* Save default security descriptor for later */
5281 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5282 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5284 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5285 tdb_prs_store(tdb_printers, kbuf, &ps);
5295 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5296 this security descriptor has been created when winbindd was
5297 down. Take ownership of security descriptor. */
5299 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5302 /* Change sd owner to workgroup administrator */
5304 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5305 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5306 SEC_DESC *psd = NULL;
5311 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5313 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5315 (*secdesc_ctr)->sd->group_sid,
5316 (*secdesc_ctr)->sd->sacl,
5317 (*secdesc_ctr)->sd->dacl,
5324 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5325 if (!new_secdesc_ctr) {
5329 /* Swap with other one */
5331 *secdesc_ctr = new_secdesc_ctr;
5335 nt_printing_setsec(sharename, *secdesc_ctr);
5339 if (DEBUGLEVEL >= 10) {
5340 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5343 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5344 sharename, the_acl->num_aces));
5346 for (i = 0; i < the_acl->num_aces; i++) {
5349 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5351 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5352 the_acl->aces[i].type, the_acl->aces[i].flags,
5353 the_acl->aces[i].access_mask));
5362 1: level not implemented
5363 2: file doesn't exist
5364 3: can't allocate memory
5365 4: can't free memory
5366 5: non existant struct
5370 A printer and a printer driver are 2 different things.
5371 NT manages them separatelly, Samba does the same.
5372 Why ? Simply because it's easier and it makes sense !
5374 Now explanation: You have 3 printers behind your samba server,
5375 2 of them are the same make and model (laser A and B). But laser B
5376 has an 3000 sheet feeder and laser A doesn't such an option.
5377 Your third printer is an old dot-matrix model for the accounting :-).
5379 If the /usr/local/samba/lib directory (default dir), you will have
5380 5 files to describe all of this.
5382 3 files for the printers (1 by printer):
5385 NTprinter_accounting
5386 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5387 NTdriver_printer model X
5388 NTdriver_printer model Y
5390 jfm: I should use this comment for the text file to explain
5391 same thing for the forms BTW.
5392 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5396 /* Convert generic access rights to printer object specific access rights.
5397 It turns out that NT4 security descriptors use generic access rights and
5398 NT5 the object specific ones. */
5400 void map_printer_permissions(SEC_DESC *sd)
5404 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5405 se_map_generic(&sd->dacl->aces[i].access_mask,
5406 &printer_generic_mapping);
5410 /****************************************************************************
5411 Check a user has permissions to perform the given operation. We use the
5412 permission constants defined in include/rpc_spoolss.h to check the various
5413 actions we perform when checking printer access.
5415 PRINTER_ACCESS_ADMINISTER:
5416 print_queue_pause, print_queue_resume, update_printer_sec,
5417 update_printer, spoolss_addprinterex_level_2,
5418 _spoolss_setprinterdata
5423 JOB_ACCESS_ADMINISTER:
5424 print_job_delete, print_job_pause, print_job_resume,
5427 Try access control in the following order (for performance reasons):
5428 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5429 2) check security descriptor (bit comparisons in memory)
5430 3) "printer admins" (may result in numerous calls to winbind)
5432 ****************************************************************************/
5433 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5435 SEC_DESC_BUF *secdesc = NULL;
5436 uint32 access_granted;
5440 TALLOC_CTX *mem_ctx = NULL;
5441 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5443 /* If user is NULL then use the current_user structure */
5446 user = ¤t_user;
5448 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5450 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5454 /* Get printer name */
5456 pname = PRINTERNAME(snum);
5458 if (!pname || !*pname) {
5463 /* Get printer security descriptor */
5465 if(!(mem_ctx = talloc_init("print_access_check"))) {
5470 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5471 talloc_destroy(mem_ctx);
5476 if (access_type == JOB_ACCESS_ADMINISTER) {
5477 SEC_DESC_BUF *parent_secdesc = secdesc;
5479 /* Create a child security descriptor to check permissions
5480 against. This is because print jobs are child objects
5481 objects of a printer. */
5483 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5486 talloc_destroy(mem_ctx);
5491 /* Now this is the bit that really confuses me. The access
5492 type needs to be changed from JOB_ACCESS_ADMINISTER to
5493 PRINTER_ACCESS_ADMINISTER for this to work. Something
5494 to do with the child (job) object becoming like a
5497 access_type = PRINTER_ACCESS_ADMINISTER;
5502 map_printer_permissions(secdesc->sd);
5504 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5505 &access_granted, &status);
5507 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5509 /* see if we need to try the printer admin list */
5511 if ((access_granted == 0) &&
5512 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5513 user->nt_user_token,
5514 lp_printer_admin(snum)))) {
5515 talloc_destroy(mem_ctx);
5519 talloc_destroy(mem_ctx);
5528 /****************************************************************************
5529 Check the time parameters allow a print operation.
5530 *****************************************************************************/
5532 BOOL print_time_access_check(const char *servicename)
5534 NT_PRINTER_INFO_LEVEL *printer = NULL;
5536 time_t now = time(NULL);
5540 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5543 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5547 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5549 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5552 free_a_printer(&printer, 2);
5560 /****************************************************************************
5561 Fill in the servername sent in the _spoolss_open_printer_ex() call
5562 ****************************************************************************/
5564 char* get_server_name( Printer_entry *printer )
5566 return printer->servername;