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(talloc_tos(),conn, name, False, &new_name, NULL, pst);
672 pstrcpy(name, new_name);
676 /*******************************************************************
677 tdb traversal function for counting printers.
678 ********************************************************************/
680 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
681 TDB_DATA data, void *context)
683 int *printer_count = (int*)context;
685 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
687 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
693 /*******************************************************************
694 Update the spooler global c_setprinter. This variable is initialized
695 when the parent smbd starts with the number of existing printers. It
696 is monotonically increased by the current number of printers *after*
697 each add or delete printer RPC. Only Microsoft knows why... JRR020119
698 ********************************************************************/
700 uint32 update_c_setprinter(BOOL initialize)
703 int32 printer_count = 0;
705 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
707 /* Traverse the tdb, counting the printers */
708 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
710 /* If initializing, set c_setprinter to current printers count
711 * otherwise, bump it by the current printer count
714 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
716 c_setprinter = printer_count;
718 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
719 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
721 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
723 return (uint32)c_setprinter;
726 /*******************************************************************
727 Get the spooler global c_setprinter, accounting for initialization.
728 ********************************************************************/
730 uint32 get_c_setprinter(void)
732 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
734 if (c_setprinter == (int32)-1)
735 c_setprinter = update_c_setprinter(True);
737 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
739 return (uint32)c_setprinter;
742 /****************************************************************************
743 Get builtin form struct list.
744 ****************************************************************************/
746 int get_builtin_ntforms(nt_forms_struct **list)
748 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
752 return sizeof(default_forms) / sizeof(default_forms[0]);
755 /****************************************************************************
756 get a builtin form struct
757 ****************************************************************************/
759 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
763 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
764 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
765 count = sizeof(default_forms) / sizeof(default_forms[0]);
766 for (i=0;i<count;i++) {
767 if (strequal(form_name,default_forms[i].name)) {
768 DEBUGADD(6,("Found builtin form %s \n", form_name));
769 memcpy(form,&default_forms[i],sizeof(*form));
777 /****************************************************************************
778 get a form struct list.
779 ****************************************************************************/
781 int get_ntforms(nt_forms_struct **list)
783 TDB_DATA kbuf, newkey, dbuf;
784 nt_forms_struct form;
791 for (kbuf = tdb_firstkey(tdb_forms);
793 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
795 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
798 dbuf = tdb_fetch(tdb_forms, kbuf);
802 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
803 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
804 &i, &form.flag, &form.width, &form.length, &form.left,
805 &form.top, &form.right, &form.bottom);
806 SAFE_FREE(dbuf.dptr);
807 if (ret != dbuf.dsize)
810 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
812 DEBUG(0,("get_ntforms: Realloc fail.\n"));
823 /****************************************************************************
824 write a form struct list
825 ****************************************************************************/
826 int write_ntforms(nt_forms_struct **list, int number)
833 for (i=0;i<number;i++) {
834 /* save index, so list is rebuilt in correct order */
835 len = tdb_pack((uint8 *)buf, sizeof(buf), "dddddddd",
836 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
837 (*list)[i].left, (*list)[i].top, (*list)[i].right,
839 if (len > sizeof(buf)) break;
840 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
842 dbuf.dptr = (uint8 *)buf;
843 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) break;
849 /****************************************************************************
850 add a form struct at the end of the list
851 ****************************************************************************/
852 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
859 * NT tries to add forms even when
860 * they are already in the base
861 * only update the values if already present
866 unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
867 for (n=0; n<*count; n++) {
868 if ( strequal((*list)[n].name, form_name) ) {
875 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
876 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
879 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
883 (*list)[n].flag=form->flags;
884 (*list)[n].width=form->size_x;
885 (*list)[n].length=form->size_y;
886 (*list)[n].left=form->left;
887 (*list)[n].top=form->top;
888 (*list)[n].right=form->right;
889 (*list)[n].bottom=form->bottom;
891 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
892 update ? "updated" : "added", form_name));
897 /****************************************************************************
898 Delete a named form struct.
899 ****************************************************************************/
901 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
909 unistr2_to_ascii(form_name, del_name, sizeof(form_name));
911 for (n=0; n<*count; n++) {
912 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
913 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
919 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
920 *ret = WERR_INVALID_PARAM;
924 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
925 if (tdb_delete_bystring(tdb_forms, key) != 0) {
933 /****************************************************************************
934 Update a form struct.
935 ****************************************************************************/
937 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
941 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
943 DEBUG(106, ("[%s]\n", form_name));
944 for (n=0; n<count; n++) {
945 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
946 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
950 if (n==count) return;
952 (*list)[n].flag=form->flags;
953 (*list)[n].width=form->size_x;
954 (*list)[n].length=form->size_y;
955 (*list)[n].left=form->left;
956 (*list)[n].top=form->top;
957 (*list)[n].right=form->right;
958 (*list)[n].bottom=form->bottom;
961 /****************************************************************************
962 Get the nt drivers list.
963 Traverse the database and look-up the matching names.
964 ****************************************************************************/
965 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
968 const char *short_archi;
970 TDB_DATA kbuf, newkey;
972 short_archi = get_short_archi(architecture);
977 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
979 for (kbuf = tdb_firstkey(tdb_drivers);
981 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
983 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
986 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
987 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
991 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
998 /****************************************************************************
999 Function to do the mapping between the long architecture name and
1001 ****************************************************************************/
1003 const char *get_short_archi(const char *long_archi)
1007 DEBUG(107,("Getting architecture dependant directory\n"));
1010 } while ( (archi_table[i].long_archi!=NULL ) &&
1011 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1013 if (archi_table[i].long_archi==NULL) {
1014 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1018 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1020 DEBUGADD(108,("index: [%d]\n", i));
1021 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1022 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1024 return archi_table[i].short_archi;
1027 /****************************************************************************
1028 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1029 There are two case to be covered here: PE (Portable Executable) and NE (New
1030 Executable) files. Both files support the same INFO structure, but PE files
1031 store the signature in unicode, and NE files store it as !unicode.
1032 returns -1 on error, 1 on version info found, and 0 on no version info found.
1033 ****************************************************************************/
1035 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1041 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1042 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1043 fname, DOS_HEADER_SIZE));
1047 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1048 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1049 fname, (unsigned long)byte_count));
1050 goto no_version_info;
1053 /* Is this really a DOS header? */
1054 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1055 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1056 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1057 goto no_version_info;
1060 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1061 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1062 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1064 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1065 goto no_version_info;
1068 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1069 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1070 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1071 fname, (unsigned long)byte_count));
1072 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1073 goto no_version_info;
1076 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1077 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1078 unsigned int num_sections;
1079 unsigned int section_table_bytes;
1081 /* Just skip over optional header to get to section table */
1082 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
1083 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1084 SEEK_CUR) == (SMB_OFF_T)-1) {
1085 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1090 /* get the section table */
1091 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1092 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1093 if (section_table_bytes == 0)
1097 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1098 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1099 fname, section_table_bytes));
1103 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1104 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1105 fname, (unsigned long)byte_count));
1109 /* Iterate the section table looking for the resource section ".rsrc" */
1110 for (i = 0; i < num_sections; i++) {
1111 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1113 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1114 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1115 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1117 if (section_bytes == 0)
1121 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1122 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1123 fname, section_bytes));
1127 /* Seek to the start of the .rsrc section info */
1128 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1129 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1134 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1135 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1136 fname, (unsigned long)byte_count));
1140 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1143 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1144 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1145 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1146 /* Align to next long address */
1147 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1149 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1150 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1151 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1153 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1154 fname, *major, *minor,
1155 (*major>>16)&0xffff, *major&0xffff,
1156 (*minor>>16)&0xffff, *minor&0xffff));
1165 /* Version info not found, fall back to origin date/time */
1166 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1170 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1171 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1172 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1173 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1174 /* At this point, we assume the file is in error. It still could be somthing
1175 * else besides a NE file, but it unlikely at this point. */
1179 /* Allocate a bit more space to speed up things */
1181 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1182 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1183 fname, PE_HEADER_SIZE));
1187 /* This is a HACK! I got tired of trying to sort through the messy
1188 * 'NE' file format. If anyone wants to clean this up please have at
1189 * it, but this works. 'NE' files will eventually fade away. JRR */
1190 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1191 /* Cover case that should not occur in a well formed 'NE' .dll file */
1192 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1194 for(i=0; i<byte_count; i++) {
1195 /* Fast skip past data that can't possibly match */
1196 if (buf[i] != 'V') continue;
1198 /* Potential match data crosses buf boundry, move it to beginning
1199 * of buf, and fill the buf with as much as it will hold. */
1200 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1203 memcpy(buf, &buf[i], byte_count-i);
1204 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1205 (byte_count-i))) < 0) {
1207 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1212 byte_count = bc + (byte_count - i);
1213 if (byte_count<VS_VERSION_INFO_SIZE) break;
1218 /* Check that the full signature string and the magic number that
1219 * follows exist (not a perfect solution, but the chances that this
1220 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1221 * twice, as it is simpler to read the code. */
1222 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1223 /* Compute skip alignment to next long address */
1224 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1225 sizeof(VS_SIGNATURE)) & 3;
1226 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1228 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1229 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1230 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1231 fname, *major, *minor,
1232 (*major>>16)&0xffff, *major&0xffff,
1233 (*minor>>16)&0xffff, *minor&0xffff));
1240 /* Version info not found, fall back to origin date/time */
1241 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1246 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1247 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1248 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1259 /****************************************************************************
1260 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1261 share one or more files. During the MS installation process files are checked
1262 to insure that only a newer version of a shared file is installed over an
1263 older version. There are several possibilities for this comparison. If there
1264 is no previous version, the new one is newer (obviously). If either file is
1265 missing the version info structure, compare the creation date (on Unix use
1266 the modification date). Otherwise chose the numerically larger version number.
1267 ****************************************************************************/
1269 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1271 BOOL use_version = True;
1276 time_t new_create_time;
1280 time_t old_create_time;
1282 files_struct *fsp = NULL;
1284 SMB_STRUCT_STAT stat_buf;
1288 SET_STAT_INVALID(st);
1289 SET_STAT_INVALID(stat_buf);
1290 new_create_time = (time_t)0;
1291 old_create_time = (time_t)0;
1293 /* Get file version info (if available) for previous file (if it exists) */
1294 pstrcpy(filepath, old_file);
1296 driver_unix_convert(conn,filepath,&stat_buf);
1298 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1300 FILE_SHARE_READ|FILE_SHARE_WRITE,
1303 FILE_ATTRIBUTE_NORMAL,
1307 if (!NT_STATUS_IS_OK(status)) {
1308 /* Old file not found, so by definition new file is in fact newer */
1309 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1314 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1320 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1322 use_version = False;
1323 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1324 old_create_time = st.st_mtime;
1325 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1328 close_file(fsp, NORMAL_CLOSE);
1330 /* Get file version info (if available) for new file */
1331 pstrcpy(filepath, new_file);
1332 driver_unix_convert(conn,filepath,&stat_buf);
1334 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1336 FILE_SHARE_READ|FILE_SHARE_WRITE,
1339 FILE_ATTRIBUTE_NORMAL,
1343 if (!NT_STATUS_IS_OK(status)) {
1344 /* New file not found, this shouldn't occur if the caller did its job */
1345 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1350 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1356 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1358 use_version = False;
1359 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1360 new_create_time = st.st_mtime;
1361 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1364 close_file(fsp, NORMAL_CLOSE);
1366 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1367 /* Compare versions and choose the larger version number */
1368 if (new_major > old_major ||
1369 (new_major == old_major && new_minor > old_minor)) {
1371 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1375 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1380 /* Compare modification time/dates and choose the newest time/date */
1381 if (new_create_time > old_create_time) {
1382 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1386 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1393 close_file(fsp, NORMAL_CLOSE);
1397 /****************************************************************************
1398 Determine the correct cVersion associated with an architecture and driver
1399 ****************************************************************************/
1400 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1401 struct current_user *user, WERROR *perr)
1408 files_struct *fsp = NULL;
1410 connection_struct *conn;
1413 SET_STAT_INVALID(st);
1415 *perr = WERR_INVALID_PARAM;
1417 /* If architecture is Windows 95/98/ME, the version is always 0. */
1418 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1419 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1424 /* If architecture is Windows x64, the version is always 3. */
1425 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1426 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1432 * Connect to the print$ share under the same account as the user connected
1433 * to the rpc pipe. Note we must still be root to do this.
1436 /* Null password is ok - we are already an authenticated user... */
1437 null_pw = data_blob_null;
1438 fstrcpy(res_type, "A:");
1440 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1444 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1445 *perr = ntstatus_to_werror(nt_status);
1449 /* We are temporarily becoming the connection user. */
1450 if (!become_user(conn, user->vuid)) {
1451 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1452 *perr = WERR_ACCESS_DENIED;
1456 /* Open the driver file (Portable Executable format) and determine the
1457 * deriver the cversion. */
1458 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1460 driver_unix_convert(conn,driverpath,&st);
1462 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1463 *perr = WERR_BADFILE;
1467 status = open_file_ntcreate(conn, NULL, driverpath, &st,
1469 FILE_SHARE_READ|FILE_SHARE_WRITE,
1472 FILE_ATTRIBUTE_NORMAL,
1476 if (!NT_STATUS_IS_OK(status)) {
1477 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1478 driverpath, errno));
1479 *perr = WERR_ACCESS_DENIED;
1484 int ret = get_file_version(fsp, driverpath, &major, &minor);
1485 if (ret == -1) goto error_exit;
1488 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1493 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1494 * for more details. Version in this case is not just the version of the
1495 * file, but the version in the sense of kernal mode (2) vs. user mode
1496 * (3) drivers. Other bits of the version fields are the version info.
1499 cversion = major & 0x0000ffff;
1501 case 2: /* WinNT drivers */
1502 case 3: /* Win2K drivers */
1506 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1507 driverpath, cversion));
1511 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1512 driverpath, major, minor));
1515 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1516 driverpath, cversion));
1518 close_file(fsp, NORMAL_CLOSE);
1519 close_cnum(conn, user->vuid);
1528 close_file(fsp, NORMAL_CLOSE);
1530 close_cnum(conn, user->vuid);
1535 /****************************************************************************
1536 ****************************************************************************/
1537 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1538 struct current_user *user)
1540 const char *architecture;
1546 /* clean up the driver name.
1547 * we can get .\driver.dll
1548 * or worse c:\windows\system\driver.dll !
1550 /* using an intermediate string to not have overlaping memcpy()'s */
1551 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1552 fstrcpy(new_name, p+1);
1553 fstrcpy(driver->driverpath, new_name);
1556 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1557 fstrcpy(new_name, p+1);
1558 fstrcpy(driver->datafile, new_name);
1561 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1562 fstrcpy(new_name, p+1);
1563 fstrcpy(driver->configfile, new_name);
1566 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1567 fstrcpy(new_name, p+1);
1568 fstrcpy(driver->helpfile, new_name);
1571 if (driver->dependentfiles) {
1572 for (i=0; *driver->dependentfiles[i]; i++) {
1573 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1574 fstrcpy(new_name, p+1);
1575 fstrcpy(driver->dependentfiles[i], new_name);
1580 architecture = get_short_archi(driver->environment);
1581 if (!architecture) {
1582 return WERR_UNKNOWN_PRINTER_DRIVER;
1585 /* jfm:7/16/2000 the client always sends the cversion=0.
1586 * The server should check which version the driver is by reading
1587 * the PE header of driver->driverpath.
1589 * For Windows 95/98 the version is 0 (so the value sent is correct)
1590 * For Windows NT (the architecture doesn't matter)
1591 * NT 3.1: cversion=0
1592 * NT 3.5/3.51: cversion=1
1596 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1602 /****************************************************************************
1603 ****************************************************************************/
1604 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1606 const char *architecture;
1612 /* clean up the driver name.
1613 * we can get .\driver.dll
1614 * or worse c:\windows\system\driver.dll !
1616 /* using an intermediate string to not have overlaping memcpy()'s */
1617 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1618 fstrcpy(new_name, p+1);
1619 fstrcpy(driver->driverpath, new_name);
1622 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1623 fstrcpy(new_name, p+1);
1624 fstrcpy(driver->datafile, new_name);
1627 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1628 fstrcpy(new_name, p+1);
1629 fstrcpy(driver->configfile, new_name);
1632 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1633 fstrcpy(new_name, p+1);
1634 fstrcpy(driver->helpfile, new_name);
1637 if (driver->dependentfiles) {
1638 for (i=0; *driver->dependentfiles[i]; i++) {
1639 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1640 fstrcpy(new_name, p+1);
1641 fstrcpy(driver->dependentfiles[i], new_name);
1646 architecture = get_short_archi(driver->environment);
1647 if (!architecture) {
1648 return WERR_UNKNOWN_PRINTER_DRIVER;
1651 /* jfm:7/16/2000 the client always sends the cversion=0.
1652 * The server should check which version the driver is by reading
1653 * the PE header of driver->driverpath.
1655 * For Windows 95/98 the version is 0 (so the value sent is correct)
1656 * For Windows NT (the architecture doesn't matter)
1657 * NT 3.1: cversion=0
1658 * NT 3.5/3.51: cversion=1
1663 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1669 /****************************************************************************
1670 ****************************************************************************/
1671 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1672 uint32 level, struct current_user *user)
1677 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1678 driver=driver_abstract.info_3;
1679 return clean_up_driver_struct_level_3(driver, user);
1683 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1684 driver=driver_abstract.info_6;
1685 return clean_up_driver_struct_level_6(driver, user);
1688 return WERR_INVALID_PARAM;
1692 /****************************************************************************
1693 This function sucks and should be replaced. JRA.
1694 ****************************************************************************/
1696 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1698 dst->cversion = src->version;
1700 fstrcpy( dst->name, src->name);
1701 fstrcpy( dst->environment, src->environment);
1702 fstrcpy( dst->driverpath, src->driverpath);
1703 fstrcpy( dst->datafile, src->datafile);
1704 fstrcpy( dst->configfile, src->configfile);
1705 fstrcpy( dst->helpfile, src->helpfile);
1706 fstrcpy( dst->monitorname, src->monitorname);
1707 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1708 dst->dependentfiles = src->dependentfiles;
1711 #if 0 /* Debugging function */
1713 static char* ffmt(unsigned char *c){
1715 static char ffmt_str[17];
1717 for (i=0; i<16; i++) {
1718 if ((c[i] < ' ') || (c[i] > '~'))
1729 /****************************************************************************
1730 ****************************************************************************/
1731 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1732 struct current_user *user, WERROR *perr)
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1735 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1736 const char *architecture;
1741 connection_struct *conn;
1749 TALLOC_CTX *ctx = talloc_tos();
1751 memset(inbuf, '\0', sizeof(inbuf));
1752 memset(outbuf, '\0', sizeof(outbuf));
1756 driver=driver_abstract.info_3;
1757 else if (level==6) {
1758 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1759 driver = &converted_driver;
1761 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1762 return WERR_UNKNOWN_LEVEL;
1765 architecture = get_short_archi(driver->environment);
1766 if (!architecture) {
1767 return WERR_UNKNOWN_PRINTER_DRIVER;
1771 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1772 * Note we must be root to do this.
1775 null_pw = data_blob_null;
1776 fstrcpy(res_type, "A:");
1778 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1782 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1783 *perr = ntstatus_to_werror(nt_status);
1784 return WERR_NO_SUCH_SHARE;
1788 * Save who we are - we are temporarily becoming the connection user.
1791 if (!become_user(conn, conn->vuid)) {
1792 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1793 return WERR_ACCESS_DENIED;
1797 * make the directories version and version\driver_name
1798 * under the architecture directory.
1800 DEBUG(5,("Creating first directory\n"));
1801 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1802 driver_unix_convert(conn,new_dir,&st);
1803 create_directory(conn, new_dir);
1805 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1806 * listed for this driver which has already been moved, skip it (note:
1807 * drivers may list the same file name several times. Then check if the
1808 * file already exists in archi\cversion\, if so, check that the version
1809 * info (or time stamps if version info is unavailable) is newer (or the
1810 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1811 * Otherwise, delete the file.
1813 * If a file is not moved to archi\cversion\ because of an error, all the
1814 * rest of the 'unmoved' driver files are removed from archi\. If one or
1815 * more of the driver's files was already moved to archi\cversion\, it
1816 * potentially leaves the driver in a partially updated state. Version
1817 * trauma will most likely occur if an client attempts to use any printer
1818 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1819 * done is appropriate... later JRR
1822 DEBUG(5,("Moving files now !\n"));
1824 if (driver->driverpath && strlen(driver->driverpath)) {
1825 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1826 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1827 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1828 driver_unix_convert(conn,new_name,&st);
1829 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1830 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1831 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1832 new_name, old_name));
1833 *perr = WERR_ACCESS_DENIED;
1839 if (driver->datafile && strlen(driver->datafile)) {
1840 if (!strequal(driver->datafile, driver->driverpath)) {
1841 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1842 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1843 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1844 driver_unix_convert(conn,new_name,&st);
1845 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1846 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1847 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1848 new_name, old_name));
1849 *perr = WERR_ACCESS_DENIED;
1856 if (driver->configfile && strlen(driver->configfile)) {
1857 if (!strequal(driver->configfile, driver->driverpath) &&
1858 !strequal(driver->configfile, driver->datafile)) {
1859 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1860 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1861 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1862 driver_unix_convert(conn,new_name,&st);
1863 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1864 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1865 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1866 new_name, old_name));
1867 *perr = WERR_ACCESS_DENIED;
1874 if (driver->helpfile && strlen(driver->helpfile)) {
1875 if (!strequal(driver->helpfile, driver->driverpath) &&
1876 !strequal(driver->helpfile, driver->datafile) &&
1877 !strequal(driver->helpfile, driver->configfile)) {
1878 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1879 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1880 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1881 driver_unix_convert(conn,new_name,&st);
1882 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1883 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1884 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1885 new_name, old_name));
1886 *perr = WERR_ACCESS_DENIED;
1893 if (driver->dependentfiles) {
1894 for (i=0; *driver->dependentfiles[i]; i++) {
1895 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1896 !strequal(driver->dependentfiles[i], driver->datafile) &&
1897 !strequal(driver->dependentfiles[i], driver->configfile) &&
1898 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1900 for (j=0; j < i; j++) {
1901 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1906 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1907 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1908 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1909 driver_unix_convert(conn,new_name,&st);
1910 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
1911 OPENX_FILE_EXISTS_TRUNCATE|
1912 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1913 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1914 new_name, old_name));
1915 *perr = WERR_ACCESS_DENIED;
1924 close_cnum(conn, user->vuid);
1927 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1930 /****************************************************************************
1931 ****************************************************************************/
1932 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1935 const char *architecture;
1943 architecture = get_short_archi(driver->environment);
1944 if (!architecture) {
1948 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1949 * \\server is added in the rpc server layer.
1950 * It does make sense to NOT store the server's name in the printer TDB.
1953 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1955 /* .inf files do not always list a file for each of the four standard files.
1956 * Don't prepend a path to a null filename, or client claims:
1957 * "The server on which the printer resides does not have a suitable
1958 * <printer driver name> printer driver installed. Click OK if you
1959 * wish to install the driver on your local machine."
1961 if (strlen(driver->driverpath)) {
1962 fstrcpy(temp_name, driver->driverpath);
1963 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1966 if (strlen(driver->datafile)) {
1967 fstrcpy(temp_name, driver->datafile);
1968 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1971 if (strlen(driver->configfile)) {
1972 fstrcpy(temp_name, driver->configfile);
1973 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1976 if (strlen(driver->helpfile)) {
1977 fstrcpy(temp_name, driver->helpfile);
1978 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1981 if (driver->dependentfiles) {
1982 for (i=0; *driver->dependentfiles[i]; i++) {
1983 fstrcpy(temp_name, driver->dependentfiles[i]);
1984 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1988 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1990 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1997 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2000 driver->environment,
2005 driver->monitorname,
2006 driver->defaultdatatype);
2008 if (driver->dependentfiles) {
2009 for (i=0; *driver->dependentfiles[i]; i++) {
2010 len += tdb_pack(buf+len, buflen-len, "f",
2011 driver->dependentfiles[i]);
2015 if (len != buflen) {
2016 buf = (uint8 *)SMB_REALLOC(buf, len);
2018 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2029 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2033 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2039 /****************************************************************************
2040 ****************************************************************************/
2041 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2043 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2046 info3.cversion = driver->version;
2047 fstrcpy(info3.name,driver->name);
2048 fstrcpy(info3.environment,driver->environment);
2049 fstrcpy(info3.driverpath,driver->driverpath);
2050 fstrcpy(info3.datafile,driver->datafile);
2051 fstrcpy(info3.configfile,driver->configfile);
2052 fstrcpy(info3.helpfile,driver->helpfile);
2053 fstrcpy(info3.monitorname,driver->monitorname);
2054 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2055 info3.dependentfiles = driver->dependentfiles;
2057 return add_a_printer_driver_3(&info3);
2061 /****************************************************************************
2062 ****************************************************************************/
2063 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2065 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2069 fstrcpy(info.name, driver);
2070 fstrcpy(info.defaultdatatype, "RAW");
2072 fstrcpy(info.driverpath, "");
2073 fstrcpy(info.datafile, "");
2074 fstrcpy(info.configfile, "");
2075 fstrcpy(info.helpfile, "");
2077 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2080 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2081 fstrcpy(info.dependentfiles[0], "");
2083 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2085 SAFE_FREE(info.dependentfiles);
2092 /****************************************************************************
2093 ****************************************************************************/
2094 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2096 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2098 const char *architecture;
2103 ZERO_STRUCT(driver);
2105 architecture = get_short_archi(arch);
2106 if ( !architecture ) {
2107 return WERR_UNKNOWN_PRINTER_DRIVER;
2110 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2112 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2115 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2117 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2119 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2121 return WERR_UNKNOWN_PRINTER_DRIVER;
2123 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2132 driver.defaultdatatype);
2135 while (len < dbuf.dsize) {
2136 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2137 if ( !driver.dependentfiles ) {
2138 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2142 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2143 &driver.dependentfiles[i]);
2147 if ( driver.dependentfiles )
2148 fstrcpy( driver.dependentfiles[i], "" );
2150 SAFE_FREE(dbuf.dptr);
2152 if (len != dbuf.dsize) {
2153 SAFE_FREE(driver.dependentfiles);
2155 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2158 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2160 SAFE_FREE(driver.dependentfiles);
2167 /****************************************************************************
2168 Debugging function, dump at level 6 the struct in the logs.
2169 ****************************************************************************/
2171 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2174 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2177 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2183 if (driver.info_3 == NULL)
2186 info3=driver.info_3;
2188 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2189 DEBUGADD(20,("name:[%s]\n", info3->name));
2190 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2191 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2192 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2193 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2194 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2195 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2196 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2198 for (i=0; info3->dependentfiles &&
2199 *info3->dependentfiles[i]; i++) {
2200 DEBUGADD(20,("dependentfile:[%s]\n",
2201 info3->dependentfiles[i]));
2208 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2216 /****************************************************************************
2217 ****************************************************************************/
2218 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2222 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2227 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2228 nt_devmode->devicename,
2229 nt_devmode->formname,
2231 nt_devmode->specversion,
2232 nt_devmode->driverversion,
2234 nt_devmode->driverextra,
2235 nt_devmode->orientation,
2236 nt_devmode->papersize,
2237 nt_devmode->paperlength,
2238 nt_devmode->paperwidth,
2241 nt_devmode->defaultsource,
2242 nt_devmode->printquality,
2245 nt_devmode->yresolution,
2246 nt_devmode->ttoption,
2247 nt_devmode->collate,
2248 nt_devmode->logpixels,
2251 nt_devmode->bitsperpel,
2252 nt_devmode->pelswidth,
2253 nt_devmode->pelsheight,
2254 nt_devmode->displayflags,
2255 nt_devmode->displayfrequency,
2256 nt_devmode->icmmethod,
2257 nt_devmode->icmintent,
2258 nt_devmode->mediatype,
2259 nt_devmode->dithertype,
2260 nt_devmode->reserved1,
2261 nt_devmode->reserved2,
2262 nt_devmode->panningwidth,
2263 nt_devmode->panningheight,
2264 nt_devmode->nt_dev_private);
2267 if (nt_devmode->nt_dev_private) {
2268 len += tdb_pack(buf+len, buflen-len, "B",
2269 nt_devmode->driverextra,
2270 nt_devmode->nt_dev_private);
2273 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2278 /****************************************************************************
2279 Pack all values in all printer keys
2280 ***************************************************************************/
2282 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2286 REGISTRY_VALUE *val;
2287 REGVAL_CTR *val_ctr;
2294 /* loop over all keys */
2296 for ( i=0; i<data->num_keys; i++ ) {
2297 val_ctr = data->keys[i].values;
2298 num_values = regval_ctr_numvals( val_ctr );
2300 /* pack the keyname followed by a empty value */
2302 len += tdb_pack(buf+len, buflen-len, "pPdB",
2303 &data->keys[i].name,
2309 /* now loop over all values */
2311 for ( j=0; j<num_values; j++ ) {
2312 /* pathname should be stored as <key>\<value> */
2314 val = regval_ctr_specific_value( val_ctr, j );
2315 pstrcpy( path, data->keys[i].name );
2316 pstrcat( path, "\\" );
2317 pstrcat( path, regval_name(val) );
2319 len += tdb_pack(buf+len, buflen-len, "pPdB",
2324 regval_data_p(val) );
2326 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2333 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2339 /****************************************************************************
2340 Delete a printer - this just deletes the printer info file, any open
2341 handles are not affected.
2342 ****************************************************************************/
2344 uint32 del_a_printer(const char *sharename)
2347 pstring printdb_path;
2349 kbuf = make_printer_tdbkey( sharename );
2350 tdb_delete(tdb_printers, kbuf);
2352 kbuf= make_printers_secdesc_tdbkey( sharename );
2353 tdb_delete(tdb_printers, kbuf);
2355 close_all_print_db();
2357 if (geteuid() == 0) {
2358 pstrcpy(printdb_path, lock_path("printing/"));
2359 pstrcat(printdb_path, sharename);
2360 pstrcat(printdb_path, ".tdb");
2362 unlink(printdb_path);
2368 /****************************************************************************
2369 ****************************************************************************/
2370 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2375 TDB_DATA kbuf, dbuf;
2378 * in addprinter: no servername and the printer is the name
2379 * in setprinter: servername is \\server
2380 * and printer is \\server\\printer
2382 * Samba manages only local printers.
2383 * we currently don't support things like i
2384 * path=\\other_server\printer
2386 * We only store the printername, not \\server\printername
2389 if ( info->servername[0] != '\0' ) {
2390 trim_string(info->printername, info->servername, NULL);
2391 trim_char(info->printername, '\\', '\0');
2392 info->servername[0]='\0';
2396 * JFM: one day I'll forget.
2397 * below that's info->portname because that's the SAMBA sharename
2398 * and I made NT 'thinks' it's the portname
2399 * the info->sharename is the thing you can name when you add a printer
2400 * that's the short-name when you create shared printer for 95/98
2401 * So I've made a limitation in SAMBA: you can only have 1 printer model
2402 * behind a SAMBA share.
2410 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2413 info->default_priority,
2430 info->printprocessor,
2434 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2436 len += pack_values( info->data, buf+len, buflen-len );
2438 if (buflen != len) {
2439 buf = (uint8 *)SMB_REALLOC(buf, len);
2441 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2450 kbuf = make_printer_tdbkey( info->sharename );
2455 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2458 if (!W_ERROR_IS_OK(ret))
2459 DEBUG(8, ("error updating printer to tdb on disk\n"));
2463 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2464 info->sharename, info->drivername, info->portname, len));
2470 /****************************************************************************
2471 Malloc and return an NT devicemode.
2472 ****************************************************************************/
2474 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2477 char adevice[MAXDEVICENAME];
2478 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2480 if (nt_devmode == NULL) {
2481 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2485 ZERO_STRUCTP(nt_devmode);
2487 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2488 fstrcpy(nt_devmode->devicename, adevice);
2490 fstrcpy(nt_devmode->formname, "Letter");
2492 nt_devmode->specversion = 0x0401;
2493 nt_devmode->driverversion = 0x0400;
2494 nt_devmode->size = 0x00DC;
2495 nt_devmode->driverextra = 0x0000;
2496 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2497 DEFAULTSOURCE | COPIES | SCALE |
2498 PAPERSIZE | ORIENTATION;
2499 nt_devmode->orientation = 1;
2500 nt_devmode->papersize = PAPER_LETTER;
2501 nt_devmode->paperlength = 0;
2502 nt_devmode->paperwidth = 0;
2503 nt_devmode->scale = 0x64;
2504 nt_devmode->copies = 1;
2505 nt_devmode->defaultsource = BIN_FORMSOURCE;
2506 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2507 nt_devmode->color = COLOR_MONOCHROME;
2508 nt_devmode->duplex = DUP_SIMPLEX;
2509 nt_devmode->yresolution = 0;
2510 nt_devmode->ttoption = TT_SUBDEV;
2511 nt_devmode->collate = COLLATE_FALSE;
2512 nt_devmode->icmmethod = 0;
2513 nt_devmode->icmintent = 0;
2514 nt_devmode->mediatype = 0;
2515 nt_devmode->dithertype = 0;
2517 /* non utilisés par un driver d'imprimante */
2518 nt_devmode->logpixels = 0;
2519 nt_devmode->bitsperpel = 0;
2520 nt_devmode->pelswidth = 0;
2521 nt_devmode->pelsheight = 0;
2522 nt_devmode->displayflags = 0;
2523 nt_devmode->displayfrequency = 0;
2524 nt_devmode->reserved1 = 0;
2525 nt_devmode->reserved2 = 0;
2526 nt_devmode->panningwidth = 0;
2527 nt_devmode->panningheight = 0;
2529 nt_devmode->nt_dev_private = NULL;
2533 /****************************************************************************
2534 Deepcopy an NT devicemode.
2535 ****************************************************************************/
2537 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2539 NT_DEVICEMODE *new_nt_devicemode = NULL;
2541 if ( !nt_devicemode )
2544 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2545 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2549 new_nt_devicemode->nt_dev_private = NULL;
2550 if (nt_devicemode->nt_dev_private != NULL) {
2551 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2552 SAFE_FREE(new_nt_devicemode);
2553 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2558 return new_nt_devicemode;
2561 /****************************************************************************
2562 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2563 ****************************************************************************/
2565 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2567 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2569 if(nt_devmode == NULL)
2572 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2574 SAFE_FREE(nt_devmode->nt_dev_private);
2575 SAFE_FREE(*devmode_ptr);
2578 /****************************************************************************
2579 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2580 ****************************************************************************/
2582 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2584 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2589 free_nt_devicemode(&info->devmode);
2591 TALLOC_FREE( *info_ptr );
2595 /****************************************************************************
2596 ****************************************************************************/
2597 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2601 NT_DEVICEMODE devmode;
2603 ZERO_STRUCT(devmode);
2605 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2607 if (!*nt_devmode) return len;
2609 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2613 &devmode.specversion,
2614 &devmode.driverversion,
2616 &devmode.driverextra,
2617 &devmode.orientation,
2619 &devmode.paperlength,
2620 &devmode.paperwidth,
2623 &devmode.defaultsource,
2624 &devmode.printquality,
2627 &devmode.yresolution,
2633 &devmode.bitsperpel,
2635 &devmode.pelsheight,
2636 &devmode.displayflags,
2637 &devmode.displayfrequency,
2641 &devmode.dithertype,
2644 &devmode.panningwidth,
2645 &devmode.panningheight,
2646 &devmode.nt_dev_private);
2648 if (devmode.nt_dev_private) {
2649 /* the len in tdb_unpack is an int value and
2650 * devmode.driverextra is only a short
2652 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2653 devmode.driverextra=(uint16)extra_len;
2655 /* check to catch an invalid TDB entry so we don't segfault */
2656 if (devmode.driverextra == 0) {
2657 devmode.nt_dev_private = NULL;
2661 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2663 SAFE_FREE(devmode.nt_dev_private);
2667 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2668 if (devmode.nt_dev_private)
2669 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2674 /****************************************************************************
2675 Allocate and initialize a new slot.
2676 ***************************************************************************/
2678 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2683 if ( !name || !data )
2686 /* allocate another slot in the NT_PRINTER_KEY array */
2688 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2689 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2695 key_index = data->num_keys;
2697 /* initialze new key */
2699 data->keys[key_index].name = talloc_strdup( data, name );
2701 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2706 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2711 /****************************************************************************
2712 search for a registry key name in the existing printer data
2713 ***************************************************************************/
2715 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2719 for ( i=0; i<data->num_keys; i++ ) {
2720 if ( strequal( data->keys[i].name, name ) ) {
2722 /* cleanup memory */
2724 TALLOC_FREE( data->keys[i].name );
2725 TALLOC_FREE( data->keys[i].values );
2727 /* if not the end of the array, move remaining elements down one slot */
2730 if ( data->num_keys && (i < data->num_keys) )
2731 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2738 return data->num_keys;
2741 /****************************************************************************
2742 search for a registry key name in the existing printer data
2743 ***************************************************************************/
2745 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2750 if ( !data || !name )
2753 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2755 /* loop over all existing keys */
2757 for ( i=0; i<data->num_keys; i++ ) {
2758 if ( strequal(data->keys[i].name, name) ) {
2759 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2769 /****************************************************************************
2770 ***************************************************************************/
2772 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2776 int num_subkeys = 0;
2778 fstring *subkeys_ptr = NULL;
2789 /* special case of asking for the top level printer data registry key names */
2791 if ( strlen(key) == 0 ) {
2792 for ( i=0; i<data->num_keys; i++ ) {
2794 /* found a match, so allocate space and copy the name */
2796 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2797 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2802 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2809 /* asking for the subkeys of some key */
2810 /* subkey paths are stored in the key name using '\' as the delimiter */
2812 for ( i=0; i<data->num_keys; i++ ) {
2813 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2815 /* if we found the exact key, then break */
2816 key_len = strlen( key );
2817 if ( strlen(data->keys[i].name) == key_len )
2820 /* get subkey path */
2822 p = data->keys[i].name + key_len;
2825 fstrcpy( subkeyname, p );
2826 if ( (p = strchr( subkeyname, '\\' )) )
2829 /* don't add a key more than once */
2831 for ( j=0; j<num_subkeys; j++ ) {
2832 if ( strequal( subkeys_ptr[j], subkeyname ) )
2836 if ( j != num_subkeys )
2839 /* found a match, so allocate space and copy the name */
2841 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2842 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2847 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2853 /* return error if the key was not found */
2855 if ( i == data->num_keys ) {
2856 SAFE_FREE(subkeys_ptr);
2861 /* tag off the end */
2864 fstrcpy(subkeys_ptr[num_subkeys], "" );
2866 *subkeys = subkeys_ptr;
2872 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2875 smb_ucs2_t conv_str[1024];
2878 regval_ctr_delvalue(ctr, val_name);
2879 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2880 STR_TERMINATE | STR_NOALIGN);
2881 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2882 (char *) conv_str, str_size);
2885 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2888 regval_ctr_delvalue(ctr, val_name);
2889 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2890 (char *) &dword, sizeof(dword));
2893 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2896 uint8 bin_bool = (b ? 1 : 0);
2897 regval_ctr_delvalue(ctr, val_name);
2898 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2899 (char *) &bin_bool, sizeof(bin_bool));
2902 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2903 const char *multi_sz)
2905 smb_ucs2_t *conv_strs = NULL;
2908 /* a multi-sz has to have a null string terminator, i.e., the last
2909 string must be followed by two nulls */
2910 str_size = strlen(multi_sz) + 2;
2911 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2916 /* Change to byte units. */
2917 str_size *= sizeof(smb_ucs2_t);
2918 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2919 STR_TERMINATE | STR_NOALIGN);
2921 regval_ctr_delvalue(ctr, val_name);
2922 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2923 (char *) conv_strs, str_size);
2924 safe_free(conv_strs);
2928 /****************************************************************************
2929 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2931 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2932 * @return BOOL indicating success or failure
2933 ***************************************************************************/
2935 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2937 REGVAL_CTR *ctr = NULL;
2940 char *allocated_string = NULL;
2941 const char *ascii_str;
2944 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2945 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2946 ctr = info2->data->keys[i].values;
2948 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2949 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2951 /* we make the assumption that the netbios name is the same
2952 as the DNS name sinc ethe former will be what we used to
2955 if ( get_mydnsdomname( dnssuffix ) )
2956 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2958 fstrcpy( longname, global_myname() );
2960 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2962 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2963 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2964 SAFE_FREE(allocated_string);
2966 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2967 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2968 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2969 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2970 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2971 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2972 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2973 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2974 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2976 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2977 (info2->attributes &
2978 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2980 switch (info2->attributes & 0x3) {
2982 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2985 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2988 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2991 ascii_str = "unknown";
2993 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2998 /*****************************************************************
2999 ****************************************************************/
3001 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3005 REGVAL_CTR *ctr=NULL;
3006 UNISTR2 unistr_guid;
3008 /* find the DsSpooler key */
3009 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3010 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3011 ctr = info2->data->keys[i].values;
3013 regval_ctr_delvalue(ctr, "objectGUID");
3015 /* We used to store this as a REG_BINARY but that causes
3018 ZERO_STRUCT( unistr_guid );
3019 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3020 UNI_STR_TERMINATE );
3022 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3023 (char *)unistr_guid.buffer,
3024 unistr_guid.uni_max_len*2);
3028 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3029 NT_PRINTER_INFO_LEVEL *printer)
3033 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3034 char *srv_dn_utf8, **srv_cn_utf8;
3037 const char *attrs[] = {"objectGUID", NULL};
3039 WERROR win_rc = WERR_OK;
3041 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3043 /* figure out where to publish */
3044 ads_find_machine_acct(ads, &res, global_myname());
3046 /* We use ldap_get_dn here as we need the answer
3047 * in utf8 to call ldap_explode_dn(). JRA. */
3049 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3052 return WERR_SERVER_UNAVAILABLE;
3054 ads_msgfree(ads, res);
3055 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3057 ldap_memfree(srv_dn_utf8);
3059 return WERR_SERVER_UNAVAILABLE;
3061 /* Now convert to CH_UNIX. */
3062 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3063 ldap_memfree(srv_dn_utf8);
3064 ldap_memfree(srv_cn_utf8);
3066 return WERR_SERVER_UNAVAILABLE;
3068 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3069 ldap_memfree(srv_dn_utf8);
3070 ldap_memfree(srv_cn_utf8);
3073 return WERR_SERVER_UNAVAILABLE;
3076 ldap_memfree(srv_dn_utf8);
3077 ldap_memfree(srv_cn_utf8);
3079 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3080 if (!srv_cn_escaped) {
3081 SAFE_FREE(srv_cn_0);
3082 ldap_memfree(srv_dn_utf8);
3084 return WERR_SERVER_UNAVAILABLE;
3086 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3087 if (!sharename_escaped) {
3088 SAFE_FREE(srv_cn_escaped);
3089 SAFE_FREE(srv_cn_0);
3090 ldap_memfree(srv_dn_utf8);
3092 return WERR_SERVER_UNAVAILABLE;
3096 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3099 SAFE_FREE(srv_cn_0);
3100 SAFE_FREE(srv_cn_escaped);
3101 SAFE_FREE(sharename_escaped);
3103 /* build the ads mods */
3104 ctx = talloc_init("nt_printer_publish_ads");
3110 mods = ads_init_mods(ctx);
3114 talloc_destroy(ctx);
3118 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3119 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3120 printer->info_2->sharename);
3123 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3124 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3125 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3127 if (!ADS_ERR_OK(ads_rc))
3128 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3130 talloc_destroy(ctx);
3132 /* retreive the guid and store it locally */
3133 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3135 ads_pull_guid(ads, res, &guid);
3136 ads_msgfree(ads, res);
3137 store_printer_guid(printer->info_2, guid);
3138 win_rc = mod_a_printer(printer, 2);
3145 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3146 NT_PRINTER_INFO_LEVEL *printer)
3150 char *prt_dn = NULL;
3152 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3154 /* remove the printer from the directory */
3155 ads_rc = ads_find_printer_on_server(ads, &res,
3156 printer->info_2->sharename, global_myname());
3158 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3159 prt_dn = ads_get_dn(ads, res);
3161 ads_msgfree(ads, res);
3164 ads_rc = ads_del_dn(ads, prt_dn);
3165 ads_memfree(ads, prt_dn);
3168 ads_msgfree(ads, res);
3172 /****************************************************************************
3173 * Publish a printer in the directory
3175 * @param snum describing printer service
3176 * @return WERROR indicating status of publishing
3177 ***************************************************************************/
3179 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3182 ADS_STRUCT *ads = NULL;
3183 NT_PRINTER_INFO_LEVEL *printer = NULL;
3186 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3187 if (!W_ERROR_IS_OK(win_rc))
3191 case SPOOL_DS_PUBLISH:
3192 case SPOOL_DS_UPDATE:
3193 /* set the DsSpooler info and attributes */
3194 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3195 win_rc = WERR_NOMEM;
3199 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3201 case SPOOL_DS_UNPUBLISH:
3202 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3205 win_rc = WERR_NOT_SUPPORTED;
3209 win_rc = mod_a_printer(printer, 2);
3210 if (!W_ERROR_IS_OK(win_rc)) {
3211 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3215 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3217 DEBUG(3, ("ads_init() failed\n"));
3218 win_rc = WERR_SERVER_UNAVAILABLE;
3221 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3222 SAFE_FREE(ads->auth.password);
3223 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3226 /* ads_connect() will find the DC for us */
3227 ads_rc = ads_connect(ads);
3228 if (!ADS_ERR_OK(ads_rc)) {
3229 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3230 win_rc = WERR_ACCESS_DENIED;
3235 case SPOOL_DS_PUBLISH:
3236 case SPOOL_DS_UPDATE:
3237 win_rc = nt_printer_publish_ads(ads, printer);
3239 case SPOOL_DS_UNPUBLISH:
3240 win_rc = nt_printer_unpublish_ads(ads, printer);
3245 free_a_printer(&printer, 2);
3250 WERROR check_published_printers(void)
3253 ADS_STRUCT *ads = NULL;
3255 int n_services = lp_numservices();
3256 NT_PRINTER_INFO_LEVEL *printer = NULL;
3258 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3260 DEBUG(3, ("ads_init() failed\n"));
3261 return WERR_SERVER_UNAVAILABLE;
3263 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3264 SAFE_FREE(ads->auth.password);
3265 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3268 /* ads_connect() will find the DC for us */
3269 ads_rc = ads_connect(ads);
3270 if (!ADS_ERR_OK(ads_rc)) {
3271 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3273 ads_kdestroy("MEMORY:prtpub_cache");
3274 return WERR_ACCESS_DENIED;
3277 for (snum = 0; snum < n_services; snum++) {
3278 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3281 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3282 lp_servicename(snum))) &&
3283 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3284 nt_printer_publish_ads(ads, printer);
3286 free_a_printer(&printer, 2);
3290 ads_kdestroy("MEMORY:prtpub_cache");
3294 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3297 NT_PRINTER_INFO_LEVEL *printer = NULL;
3299 REGISTRY_VALUE *guid_val;
3304 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3306 if (!W_ERROR_IS_OK(win_rc) ||
3307 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3308 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3309 !(ctr = printer->info_2->data->keys[i].values) ||
3310 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3312 free_a_printer(&printer, 2);
3316 /* fetching printer guids really ought to be a separate function. */
3321 /* We used to store the guid as REG_BINARY, then swapped
3322 to REG_SZ for Vista compatibility so check for both */
3324 switch ( regval_type(guid_val) ){
3326 rpcstr_pull( guid_str, regval_data_p(guid_val),
3327 sizeof(guid_str)-1, -1, STR_TERMINATE );
3328 ret = smb_string_to_uuid( guid_str, guid );
3331 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3335 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3338 DEBUG(0,("is_printer_published: GUID value stored as "
3339 "invaluid type (%d)\n", regval_type(guid_val) ));
3344 free_a_printer(&printer, 2);
3348 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3353 WERROR check_published_printers(void)
3358 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3363 #endif /* HAVE_ADS */
3365 /****************************************************************************
3366 ***************************************************************************/
3368 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3370 NT_PRINTER_DATA *data;
3372 int removed_keys = 0;
3376 empty_slot = data->num_keys;
3379 return WERR_INVALID_PARAM;
3381 /* remove all keys */
3383 if ( !strlen(key) ) {
3385 TALLOC_FREE( data );
3389 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3395 /* remove a specific key (and all subkeys) */
3397 for ( i=0; i<data->num_keys; i++ ) {
3398 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3399 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3400 data->keys[i].name));
3402 TALLOC_FREE( data->keys[i].name );
3403 TALLOC_FREE( data->keys[i].values );
3405 /* mark the slot as empty */
3407 ZERO_STRUCTP( &data->keys[i] );
3411 /* find the first empty slot */
3413 for ( i=0; i<data->num_keys; i++ ) {
3414 if ( !data->keys[i].name ) {
3421 if ( i == data->num_keys )
3422 /* nothing was removed */
3423 return WERR_INVALID_PARAM;
3425 /* move everything down */
3427 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3428 if ( data->keys[i].name ) {
3429 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3430 ZERO_STRUCTP( &data->keys[i] );
3438 data->num_keys -= removed_keys;
3440 /* sanity check to see if anything is left */
3442 if ( !data->num_keys ) {
3443 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3445 SAFE_FREE( data->keys );
3446 ZERO_STRUCTP( data );
3452 /****************************************************************************
3453 ***************************************************************************/
3455 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3457 WERROR result = WERR_OK;
3460 /* we must have names on non-zero length */
3462 if ( !key || !*key|| !value || !*value )
3463 return WERR_INVALID_NAME;
3465 /* find the printer key first */
3467 key_index = lookup_printerkey( p2->data, key );
3468 if ( key_index == -1 )
3471 /* make sure the value exists so we can return the correct error code */
3473 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3474 return WERR_BADFILE;
3476 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3478 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3484 /****************************************************************************
3485 ***************************************************************************/
3487 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3488 uint32 type, uint8 *data, int real_len )
3490 WERROR result = WERR_OK;
3493 /* we must have names on non-zero length */
3495 if ( !key || !*key|| !value || !*value )
3496 return WERR_INVALID_NAME;
3498 /* find the printer key first */
3500 key_index = lookup_printerkey( p2->data, key );
3501 if ( key_index == -1 )
3502 key_index = add_new_printer_key( p2->data, key );
3504 if ( key_index == -1 )
3507 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3508 type, (const char *)data, real_len );
3510 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3511 key, value, type, real_len ));
3516 /****************************************************************************
3517 ***************************************************************************/
3519 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3523 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3526 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3529 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3532 /****************************************************************************
3533 Unpack a list of registry values frem the TDB
3534 ***************************************************************************/
3536 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3540 pstring string, valuename, keyname;
3544 REGISTRY_VALUE *regval_p;
3547 /* add the "PrinterDriverData" key first for performance reasons */
3549 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3551 /* loop and unpack the rest of the registry values */
3555 /* check to see if there are any more registry values */
3558 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3562 /* unpack the next regval */
3564 len += tdb_unpack(buf+len, buflen-len, "fdB",
3570 /* lookup for subkey names which have a type of REG_NONE */
3571 /* there's no data with this entry */
3573 if ( type == REG_NONE ) {
3574 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3575 add_new_printer_key( printer_data, string );
3580 * break of the keyname from the value name.
3581 * Valuenames can have embedded '\'s so be careful.
3582 * only support one level of keys. See the
3583 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3587 str = strchr_m( string, '\\');
3589 /* Put in "PrinterDriverData" is no key specified */
3592 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3593 pstrcpy( valuename, string );
3597 pstrcpy( keyname, string );
3598 pstrcpy( valuename, str+1 );
3601 /* see if we need a new key */
3603 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3604 key_index = add_new_printer_key( printer_data, keyname );
3606 if ( key_index == -1 ) {
3607 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3612 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3614 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3615 Thanks to Martin Zielinski for the hint. */
3617 if ( type == REG_BINARY &&
3618 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3619 strequal( valuename, "objectGUID" ) )
3622 UNISTR2 unistr_guid;
3624 ZERO_STRUCT( unistr_guid );
3626 /* convert the GUID to a UNICODE string */
3628 memcpy( &guid, data_p, sizeof(struct GUID) );
3630 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3631 UNI_STR_TERMINATE );
3633 regval_ctr_addvalue( printer_data->keys[key_index].values,
3635 (const char *)unistr_guid.buffer,
3636 unistr_guid.uni_str_len*2 );
3641 regval_ctr_addvalue( printer_data->keys[key_index].values,
3642 valuename, type, (const char *)data_p,
3647 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3654 /****************************************************************************
3655 ***************************************************************************/
3657 static void map_to_os2_driver(fstring drivername)
3659 static BOOL initialised=False;
3660 static fstring last_from,last_to;
3661 char *mapfile = lp_os2_driver_map();
3662 char **lines = NULL;
3666 if (!strlen(drivername))
3673 *last_from = *last_to = 0;
3677 if (strequal(drivername,last_from)) {
3678 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3679 fstrcpy(drivername,last_to);
3683 lines = file_lines_load(mapfile, &numlines,0);
3684 if (numlines == 0 || lines == NULL) {
3685 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3690 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3692 for( i = 0; i < numlines; i++) {
3693 char *nt_name = lines[i];
3694 char *os2_name = strchr(nt_name,'=');
3701 while (isspace(*nt_name))
3704 if (!*nt_name || strchr("#;",*nt_name))
3708 int l = strlen(nt_name);
3709 while (l && isspace(nt_name[l-1])) {
3715 while (isspace(*os2_name))
3719 int l = strlen(os2_name);
3720 while (l && isspace(os2_name[l-1])) {
3726 if (strequal(nt_name,drivername)) {
3727 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3728 fstrcpy(last_from,drivername);
3729 fstrcpy(last_to,os2_name);
3730 fstrcpy(drivername,os2_name);
3731 file_lines_free(lines);
3736 file_lines_free(lines);
3739 /****************************************************************************
3740 Get a default printer info 2 struct.
3741 ****************************************************************************/
3742 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3744 int snum = lp_servicenumber(sharename);
3746 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3747 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3748 servername, sharename);
3749 fstrcpy(info->sharename, sharename);
3750 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3752 /* by setting the driver name to an empty string, a local NT admin
3753 can now run the **local** APW to install a local printer driver
3754 for a Samba shared printer in 2.2. Without this, drivers **must** be
3755 installed on the Samba server for NT clients --jerry */
3756 #if 0 /* JERRY --do not uncomment-- */
3757 if (!*info->drivername)
3758 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3762 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3764 pstrcpy(info->comment, "");
3765 fstrcpy(info->printprocessor, "winprint");
3766 fstrcpy(info->datatype, "RAW");
3769 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3770 /* Pull the location and comment strings from cups if we don't
3772 if ( !strlen(info->location) || !strlen(info->comment) )
3773 cups_pull_comment_location( info );
3777 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3779 info->starttime = 0; /* Minutes since 12:00am GMT */
3780 info->untiltime = 0; /* Minutes since 12:00am GMT */
3782 info->default_priority = 1;
3783 info->setuptime = (uint32)time(NULL);
3786 * I changed this as I think it is better to have a generic
3787 * DEVMODE than to crash Win2k explorer.exe --jerry
3788 * See the HP Deskjet 990c Win2k drivers for an example.
3790 * However the default devmode appears to cause problems
3791 * with the HP CLJ 8500 PCL driver. Hence the addition of
3792 * the "default devmode" parameter --jerry 22/01/2002
3795 if (lp_default_devmode(snum)) {
3796 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3800 info->devmode = NULL;
3803 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3811 free_nt_devicemode(&info->devmode);
3813 return WERR_ACCESS_DENIED;
3816 /****************************************************************************
3817 ****************************************************************************/
3818 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3821 int snum = lp_servicenumber(sharename);
3822 TDB_DATA kbuf, dbuf;
3823 fstring printername;
3824 char adevice[MAXDEVICENAME];
3826 kbuf = make_printer_tdbkey( sharename );
3828 dbuf = tdb_fetch(tdb_printers, kbuf);
3830 return get_a_printer_2_default(info, servername, sharename);
3833 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3836 &info->default_priority,
3843 &info->c_setprinter,
3853 info->printprocessor,
3857 /* Samba has to have shared raw drivers. */
3858 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3859 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3861 /* Restore the stripped strings. */
3862 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3864 if ( lp_force_printername(snum) ) {
3865 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3867 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3870 fstrcpy(info->printername, printername);
3873 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3874 /* Pull the location and comment strings from cups if we don't
3876 if ( !strlen(info->location) || !strlen(info->comment) )
3877 cups_pull_comment_location( info );
3881 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3884 * Some client drivers freak out if there is a NULL devmode
3885 * (probably the driver is not checking before accessing
3886 * the devmode pointer) --jerry
3888 * See comments in get_a_printer_2_default()
3891 if (lp_default_devmode(snum) && !info->devmode) {
3892 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3894 info->devmode = construct_nt_devicemode(printername);
3897 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3898 if (info->devmode) {
3899 fstrcpy(info->devmode->devicename, adevice);
3902 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3903 DEBUG(0,("unpack_values: talloc() failed!\n"));
3904 SAFE_FREE(dbuf.dptr);
3907 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3909 /* This will get the current RPC talloc context, but we should be
3910 passing this as a parameter... fixme... JRA ! */
3912 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3913 SAFE_FREE(dbuf.dptr);
3917 /* Fix for OS/2 drivers. */
3919 if (get_remote_arch() == RA_OS2) {
3920 map_to_os2_driver(info->drivername);
3923 SAFE_FREE(dbuf.dptr);
3925 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3926 sharename, info->printername, info->drivername));
3931 /****************************************************************************
3932 Debugging function, dump at level 6 the struct in the logs.
3933 ****************************************************************************/
3934 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3937 NT_PRINTER_INFO_LEVEL_2 *info2;
3939 DEBUG(106,("Dumping printer at level [%d]\n", level));
3944 if (printer->info_2 == NULL)
3948 info2=printer->info_2;
3950 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3951 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3952 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3953 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3954 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3955 DEBUGADD(106,("status:[%d]\n", info2->status));
3956 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3957 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3958 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3959 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3960 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3962 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3963 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3964 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3965 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3966 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3967 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3968 DEBUGADD(106,("location:[%s]\n", info2->location));
3969 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3970 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3971 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3972 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3978 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3986 /****************************************************************************
3987 Update the changeid time.
3988 This is SO NASTY as some drivers need this to change, others need it
3989 static. This value will change every second, and I must hope that this
3990 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3992 ****************************************************************************/
3994 static uint32 rev_changeid(void)
3998 get_process_uptime(&tv);
4001 /* Return changeid as msec since spooler restart */
4002 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4005 * This setting seems to work well but is too untested
4006 * to replace the above calculation. Left in for experiementation
4007 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4009 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4015 * The function below are the high level ones.
4016 * only those ones must be called from the spoolss code.
4020 /****************************************************************************
4021 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4022 ****************************************************************************/
4024 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4028 dump_a_printer(printer, level);
4034 * Update the changestamp. Emperical tests show that the
4035 * ChangeID is always updated,but c_setprinter is
4036 * global spooler variable (not per printer).
4039 /* ChangeID **must** be increasing over the lifetime
4040 of client's spoolss service in order for the
4041 client's cache to show updates */
4043 printer->info_2->changeid = rev_changeid();
4046 * Because one day someone will ask:
4047 * NT->NT An admin connection to a remote
4048 * printer show changes imeediately in
4049 * the properities dialog
4051 * A non-admin connection will only show the
4052 * changes after viewing the properites page
4053 * 2 times. Seems to be related to a
4054 * race condition in the client between the spooler
4055 * updating the local cache and the Explorer.exe GUI
4056 * actually displaying the properties.
4058 * This is fixed in Win2k. admin/non-admin
4059 * connections both display changes immediately.
4064 result=update_a_printer_2(printer->info_2);
4069 result=WERR_UNKNOWN_LEVEL;
4076 /****************************************************************************
4077 Initialize printer devmode & data with previously saved driver init values.
4078 ****************************************************************************/
4080 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4085 NT_PRINTER_INFO_LEVEL_2 info;
4091 * Delete any printer data 'values' already set. When called for driver
4092 * replace, there will generally be some, but during an add printer, there
4093 * should not be any (if there are delete them).
4096 if ( info_ptr->data )
4097 delete_all_printer_data( info_ptr, "" );
4099 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4101 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4104 * When changing to a driver that has no init info in the tdb, remove
4105 * the previous drivers init info and leave the new on blank.
4107 free_nt_devicemode(&info_ptr->devmode);
4112 * Get the saved DEVMODE..
4115 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4118 * The saved DEVMODE contains the devicename from the printer used during
4119 * the initialization save. Change it to reflect the new printer.
4122 if ( info.devmode ) {
4123 ZERO_STRUCT(info.devmode->devicename);
4124 fstrcpy(info.devmode->devicename, info_ptr->printername);
4128 * NT/2k does not change out the entire DeviceMode of a printer
4129 * when changing the driver. Only the driverextra, private, &
4130 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4132 * Later examination revealed that Windows NT/2k does reset the
4133 * the printer's device mode, bit **only** when you change a
4134 * property of the device mode such as the page orientation.
4139 /* Bind the saved DEVMODE to the new the printer */
4141 free_nt_devicemode(&info_ptr->devmode);
4142 info_ptr->devmode = info.devmode;
4144 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4145 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4147 /* Add the printer data 'values' to the new printer */
4149 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4150 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4154 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4157 SAFE_FREE(dbuf.dptr);
4162 /****************************************************************************
4163 Initialize printer devmode & data with previously saved driver init values.
4164 When a printer is created using AddPrinter, the drivername bound to the
4165 printer is used to lookup previously saved driver initialization info, which
4166 is bound to the new printer.
4167 ****************************************************************************/
4169 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4171 BOOL result = False;
4175 result = set_driver_init_2(printer->info_2);
4179 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4187 /****************************************************************************
4188 Delete driver init data stored for a specified driver
4189 ****************************************************************************/
4191 BOOL del_driver_init(char *drivername)
4195 if (!drivername || !*drivername) {
4196 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4200 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4202 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4204 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4207 /****************************************************************************
4208 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4209 in the tdb. Note: this is different from the driver entry and the printer
4210 entry. There should be a single driver init entry for each driver regardless
4211 of whether it was installed from NT or 2K. Technically, they should be
4212 different, but they work out to the same struct.
4213 ****************************************************************************/
4215 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4219 int buflen, len, ret;
4227 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4229 len += pack_values( info->data, buf+len, buflen-len );
4232 buf = (uint8 *)SMB_REALLOC(buf, len);
4234 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4242 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4247 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4251 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4255 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4256 info->sharename, info->drivername));
4261 /****************************************************************************
4262 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4263 ****************************************************************************/
4265 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4269 dump_a_printer(printer, level);
4273 result = update_driver_init_2(printer->info_2);
4283 /****************************************************************************
4284 Convert the printer data value, a REG_BINARY array, into an initialization
4285 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4286 got to keep the endians happy :).
4287 ****************************************************************************/
4289 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4291 BOOL result = False;
4295 ZERO_STRUCT(devmode);
4297 prs_init(&ps, 0, ctx, UNMARSHALL);
4298 ps.data_p = (char *)data;
4299 ps.buffer_size = data_len;
4301 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4302 result = convert_devicemode("", &devmode, &nt_devmode);
4304 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4309 /****************************************************************************
4310 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4312 1. Use the driver's config DLL to this UNC printername and:
4313 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4314 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4315 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4317 The last step triggers saving the "driver initialization" information for
4318 this printer into the tdb. Later, new printers that use this driver will
4319 have this initialization information bound to them. This simulates the
4320 driver initialization, as if it had run on the Samba server (as it would
4323 The Win32 client side code requirement sucks! But until we can run arbitrary
4324 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4326 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4327 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4328 about it and you will realize why. JRR 010720
4329 ****************************************************************************/
4331 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4333 WERROR status = WERR_OK;
4334 TALLOC_CTX *ctx = NULL;
4335 NT_DEVICEMODE *nt_devmode = NULL;
4336 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4339 * When the DEVMODE is already set on the printer, don't try to unpack it.
4341 DEBUG(8,("save_driver_init_2: Enter...\n"));
4343 if ( !printer->info_2->devmode && data_len ) {
4345 * Set devmode on printer info, so entire printer initialization can be
4349 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4352 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4353 status = WERR_NOMEM;
4357 ZERO_STRUCTP(nt_devmode);
4360 * The DEVMODE is held in the 'data' component of the param in raw binary.
4361 * Convert it to to a devmode structure
4363 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4364 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4365 status = WERR_INVALID_PARAM;
4369 printer->info_2->devmode = nt_devmode;
4373 * Pack up and add (or update) the DEVMODE and any current printer data to
4374 * a 'driver init' element in the tdb
4378 if ( update_driver_init(printer, 2) != 0 ) {
4379 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4380 status = WERR_NOMEM;
4385 * If driver initialization info was successfully saved, set the current
4386 * printer to match it. This allows initialization of the current printer
4387 * as well as the driver.
4389 status = mod_a_printer(printer, 2);
4390 if (!W_ERROR_IS_OK(status)) {
4391 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4392 printer->info_2->printername));
4396 talloc_destroy(ctx);
4397 free_nt_devicemode( &nt_devmode );
4399 printer->info_2->devmode = tmp_devmode;
4404 /****************************************************************************
4405 Update the driver init info (DEVMODE and specifics) for a printer
4406 ****************************************************************************/
4408 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4410 WERROR status = WERR_OK;
4414 status = save_driver_init_2( printer, data, data_len );
4417 status = WERR_UNKNOWN_LEVEL;
4424 /****************************************************************************
4425 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4427 Previously the code had a memory allocation problem because it always
4428 used the TALLOC_CTX from the Printer_entry*. This context lasts
4429 as a long as the original handle is open. So if the client made a lot
4430 of getprinter[data]() calls, the memory usage would climb. Now we use
4431 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4432 still use the Printer_entry->ctx for maintaining the cache copy though
4433 since that object must live as long as the handle by definition.
4436 ****************************************************************************/
4438 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4439 const char *sharename)
4444 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4446 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4447 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4453 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4454 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4455 TALLOC_FREE( *pp_printer );
4460 fstrcpy( servername, print_hnd->servername );
4462 fstrcpy( servername, "%L" );
4463 standard_sub_basic( "", "", servername,
4464 sizeof(servername)-1 );
4467 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4470 /* we have a new printer now. Save it with this handle */
4472 if ( !W_ERROR_IS_OK(result) ) {
4473 TALLOC_FREE( *pp_printer );
4474 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4475 sharename, (unsigned int)level, dos_errstr(result)));
4479 dump_a_printer( *pp_printer, level);
4484 TALLOC_FREE( *pp_printer );
4485 return WERR_UNKNOWN_LEVEL;
4491 /****************************************************************************
4492 Deletes a NT_PRINTER_INFO_LEVEL struct.
4493 ****************************************************************************/
4495 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4497 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4504 if ( printer->info_2 )
4505 free_nt_printer_info_level_2(&printer->info_2);
4509 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4513 TALLOC_FREE(*pp_printer);
4518 /****************************************************************************
4519 ****************************************************************************/
4520 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4523 DEBUG(104,("adding a printer at level [%d]\n", level));
4524 dump_a_printer_driver(driver, level);
4528 result=add_a_printer_driver_3(driver.info_3);
4532 result=add_a_printer_driver_6(driver.info_6);
4542 /****************************************************************************
4543 ****************************************************************************/
4545 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4546 fstring drivername, const char *architecture, uint32 version)
4552 /* Sometime we just want any version of the driver */
4554 if ( version == DRIVER_ANY_VERSION ) {
4555 /* look for Win2k first and then for NT4 */
4556 result = get_a_printer_driver_3(&driver->info_3, drivername,
4559 if ( !W_ERROR_IS_OK(result) ) {
4560 result = get_a_printer_driver_3( &driver->info_3,
4561 drivername, architecture, 2 );
4564 result = get_a_printer_driver_3(&driver->info_3, drivername,
4565 architecture, version);
4574 if (W_ERROR_IS_OK(result))
4575 dump_a_printer_driver(*driver, level);
4580 /****************************************************************************
4581 ****************************************************************************/
4582 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4589 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4590 if (driver.info_3 != NULL)
4592 info3=driver.info_3;
4593 SAFE_FREE(info3->dependentfiles);
4594 ZERO_STRUCTP(info3);
4604 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4605 if (driver.info_6 != NULL) {
4606 info6=driver.info_6;
4607 SAFE_FREE(info6->dependentfiles);
4608 SAFE_FREE(info6->previousnames);
4609 ZERO_STRUCTP(info6);
4625 /****************************************************************************
4626 Determine whether or not a particular driver is currently assigned
4628 ****************************************************************************/
4630 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4633 int n_services = lp_numservices();
4634 NT_PRINTER_INFO_LEVEL *printer = NULL;
4635 BOOL in_use = False;
4640 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4642 /* loop through the printers.tdb and check for the drivername */
4644 for (snum=0; snum<n_services && !in_use; snum++) {
4645 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4648 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4651 if ( strequal(info_3->name, printer->info_2->drivername) )
4654 free_a_printer( &printer, 2 );
4657 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4660 NT_PRINTER_DRIVER_INFO_LEVEL d;
4663 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4665 /* we can still remove the driver if there is one of
4666 "Windows NT x86" version 2 or 3 left */
4668 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4669 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4672 switch ( info_3->cversion ) {
4674 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4677 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4680 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4682 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4687 /* now check the error code */
4689 if ( W_ERROR_IS_OK(werr) ) {
4690 /* it's ok to remove the driver, we have other architctures left */
4692 free_a_printer_driver( d, 3 );
4696 /* report that the driver is not in use by default */
4702 /**********************************************************************
4703 Check to see if a ogiven file is in use by *info
4704 *********************************************************************/
4706 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4713 if ( strequal(file, info->driverpath) )
4716 if ( strequal(file, info->datafile) )
4719 if ( strequal(file, info->configfile) )
4722 if ( strequal(file, info->helpfile) )
4725 /* see of there are any dependent files to examine */
4727 if ( !info->dependentfiles )
4730 while ( *info->dependentfiles[i] ) {
4731 if ( strequal(file, info->dependentfiles[i]) )
4740 /**********************************************************************
4741 Utility function to remove the dependent file pointed to by the
4742 input parameter from the list
4743 *********************************************************************/
4745 static void trim_dependent_file( fstring files[], int idx )
4748 /* bump everything down a slot */
4750 while( *files[idx+1] ) {
4751 fstrcpy( files[idx], files[idx+1] );
4760 /**********************************************************************
4761 Check if any of the files used by src are also used by drv
4762 *********************************************************************/
4764 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4765 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4767 BOOL in_use = False;
4773 /* check each file. Remove it from the src structure if it overlaps */
4775 if ( drv_file_in_use(src->driverpath, drv) ) {
4777 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4778 fstrcpy( src->driverpath, "" );
4781 if ( drv_file_in_use(src->datafile, drv) ) {
4783 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4784 fstrcpy( src->datafile, "" );
4787 if ( drv_file_in_use(src->configfile, drv) ) {
4789 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4790 fstrcpy( src->configfile, "" );
4793 if ( drv_file_in_use(src->helpfile, drv) ) {
4795 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4796 fstrcpy( src->helpfile, "" );
4799 /* are there any dependentfiles to examine? */
4801 if ( !src->dependentfiles )
4804 while ( *src->dependentfiles[i] ) {
4805 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4807 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4808 trim_dependent_file( src->dependentfiles, i );
4816 /****************************************************************************
4817 Determine whether or not a particular driver files are currently being
4818 used by any other driver.
4820 Return value is True if any files were in use by other drivers
4821 and False otherwise.
4823 Upon return, *info has been modified to only contain the driver files
4824 which are not in use
4825 ****************************************************************************/
4827 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4832 fstring *list = NULL;
4833 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4838 version = info->cversion;
4840 /* loop over all driver versions */
4842 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4844 /* get the list of drivers */
4847 ndrivers = get_ntdrivers(&list, info->environment, version);
4849 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4850 ndrivers, info->environment, version));
4852 /* check each driver for overlap in files */
4854 for (i=0; i<ndrivers; i++) {
4855 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4857 ZERO_STRUCT(driver);
4859 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4864 /* check if d2 uses any files from d1 */
4865 /* only if this is a different driver than the one being deleted */
4867 if ( !strequal(info->name, driver.info_3->name) ) {
4868 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4869 free_a_printer_driver(driver, 3);
4875 free_a_printer_driver(driver, 3);
4880 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4882 driver.info_3 = info;
4884 if ( DEBUGLEVEL >= 20 )
4885 dump_a_printer_driver( driver, 3 );
4890 /****************************************************************************
4891 Actually delete the driver files. Make sure that
4892 printer_driver_files_in_use() return False before calling
4894 ****************************************************************************/
4896 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4901 connection_struct *conn;
4910 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4913 * Connect to the print$ share under the same account as the
4914 * user connected to the rpc pipe. Note we must be root to
4918 null_pw = data_blob_null;
4919 fstrcpy(res_type, "A:");
4921 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4925 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4929 if ( !CAN_WRITE(conn) ) {
4930 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4934 /* Save who we are - we are temporarily becoming the connection user. */
4936 if ( !become_user(conn, conn->vuid) ) {
4937 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4941 /* now delete the files; must strip the '\print$' string from
4944 if ( *info_3->driverpath ) {
4945 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4947 driver_unix_convert(conn,file,&st);
4948 DEBUG(10,("deleting driverfile [%s]\n", s));
4949 unlink_internals(conn, NULL, 0, file, False);
4953 if ( *info_3->configfile ) {
4954 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4956 driver_unix_convert(conn,file,&st);
4957 DEBUG(10,("deleting configfile [%s]\n", s));
4958 unlink_internals(conn, NULL, 0, file, False);
4962 if ( *info_3->datafile ) {
4963 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4965 driver_unix_convert(conn,file,&st);
4966 DEBUG(10,("deleting datafile [%s]\n", s));
4967 unlink_internals(conn, NULL, 0, file, False);
4971 if ( *info_3->helpfile ) {
4972 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4974 driver_unix_convert(conn,file,&st);
4975 DEBUG(10,("deleting helpfile [%s]\n", s));
4976 unlink_internals(conn, NULL, 0, file, False);
4980 /* check if we are done removing files */
4982 if ( info_3->dependentfiles ) {
4983 while ( info_3->dependentfiles[i][0] ) {
4986 /* bypass the "\print$" portion of the path */
4988 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4990 driver_unix_convert(conn,file,&st);
4991 DEBUG(10,("deleting dependent file [%s]\n", file));
4992 unlink_internals(conn, NULL, 0, file, False);
5004 /****************************************************************************
5005 Remove a printer driver from the TDB. This assumes that the the driver was
5006 previously looked up.
5007 ***************************************************************************/
5009 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5010 uint32 version, BOOL delete_files )
5015 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5017 /* delete the tdb data first */
5019 arch = get_short_archi(info_3->environment);
5021 return WERR_UNKNOWN_PRINTER_DRIVER;
5023 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5024 arch, version, info_3->name);
5026 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5027 key, delete_files ? "TRUE" : "FALSE" ));
5029 ctr.info_3 = info_3;
5030 dump_a_printer_driver( ctr, 3 );
5032 /* check if the driver actually exists for this environment */
5034 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5036 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5037 return WERR_UNKNOWN_PRINTER_DRIVER;
5040 SAFE_FREE( dbuf.dptr );
5042 /* ok... the driver exists so the delete should return success */
5044 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5045 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5046 return WERR_ACCESS_DENIED;
5050 * now delete any associated files if delete_files == True
5051 * even if this part failes, we return succes because the
5052 * driver doesn not exist any more
5056 delete_driver_files( info_3, user );
5059 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5064 /****************************************************************************
5065 Store a security desc for a printer.
5066 ****************************************************************************/
5068 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5070 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5071 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5073 TALLOC_CTX *mem_ctx = NULL;
5077 mem_ctx = talloc_init("nt_printing_setsec");
5078 if (mem_ctx == NULL)
5081 /* The old owner and group sids of the security descriptor are not
5082 present when new ACEs are added or removed by changing printer
5083 permissions through NT. If they are NULL in the new security
5084 descriptor then copy them over from the old one. */
5086 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5087 DOM_SID *owner_sid, *group_sid;
5088 SEC_ACL *dacl, *sacl;
5089 SEC_DESC *psd = NULL;
5092 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5093 status = WERR_NOMEM;
5097 /* Pick out correct owner and group sids */
5099 owner_sid = secdesc_ctr->sd->owner_sid ?
5100 secdesc_ctr->sd->owner_sid :
5101 old_secdesc_ctr->sd->owner_sid;
5103 group_sid = secdesc_ctr->sd->group_sid ?
5104 secdesc_ctr->sd->group_sid :
5105 old_secdesc_ctr->sd->group_sid;
5107 dacl = secdesc_ctr->sd->dacl ?
5108 secdesc_ctr->sd->dacl :
5109 old_secdesc_ctr->sd->dacl;
5111 sacl = secdesc_ctr->sd->sacl ?
5112 secdesc_ctr->sd->sacl :
5113 old_secdesc_ctr->sd->sacl;
5115 /* Make a deep copy of the security descriptor */
5117 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5118 owner_sid, group_sid,
5124 status = WERR_NOMEM;
5128 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5131 if (!new_secdesc_ctr) {
5132 new_secdesc_ctr = secdesc_ctr;
5135 /* Store the security descriptor in a tdb */
5137 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5138 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5140 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5142 status = WERR_BADFUNC;
5146 kbuf = make_printers_secdesc_tdbkey( sharename );
5148 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5151 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5152 status = WERR_BADFUNC;
5155 /* Free malloc'ed memory */
5161 talloc_destroy(mem_ctx);
5165 /****************************************************************************
5166 Construct a default security descriptor buffer for a printer.
5167 ****************************************************************************/
5169 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5171 SEC_ACE ace[5]; /* max number of ace entries */
5174 SEC_ACL *psa = NULL;
5175 SEC_DESC_BUF *sdb = NULL;
5176 SEC_DESC *psd = NULL;
5180 /* Create an ACE where Everyone is allowed to print */
5182 init_sec_access(&sa, PRINTER_ACE_PRINT);
5183 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5184 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5186 /* Add the domain admins group if we are a DC */
5189 DOM_SID domadmins_sid;
5191 sid_copy(&domadmins_sid, get_global_sam_sid());
5192 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5194 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5195 init_sec_ace(&ace[i++], &domadmins_sid,
5196 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5197 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5198 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5199 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5201 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5202 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5204 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5205 init_sec_ace(&ace[i++], &adm_sid,
5206 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5207 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5208 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5209 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5212 /* add BUILTIN\Administrators as FULL CONTROL */
5214 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5215 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5216 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5217 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5218 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5219 SEC_ACE_TYPE_ACCESS_ALLOWED,
5220 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5222 /* Make the security descriptor owned by the BUILTIN\Administrators */
5224 /* The ACL revision number in rpc_secdesc.h differs from the one
5225 created by NT when setting ACE entries in printer
5226 descriptors. NT4 complains about the property being edited by a
5229 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5230 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5231 &global_sid_Builtin_Administrators,
5232 &global_sid_Builtin_Administrators,
5233 NULL, psa, &sd_size);
5237 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5241 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5243 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5244 (unsigned int)sd_size));
5249 /****************************************************************************
5250 Get a security desc for a printer.
5251 ****************************************************************************/
5253 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5259 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5260 sharename = temp + 1;
5265 /* Fetch security descriptor from tdb */
5267 kbuf = make_printers_secdesc_tdbkey( sharename );
5269 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5270 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5274 DEBUG(4,("using default secdesc for %s\n", sharename));
5276 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5280 /* Save default security descriptor for later */
5282 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5283 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5285 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5286 tdb_prs_store(tdb_printers, kbuf, &ps);
5296 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5297 this security descriptor has been created when winbindd was
5298 down. Take ownership of security descriptor. */
5300 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5303 /* Change sd owner to workgroup administrator */
5305 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5306 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5307 SEC_DESC *psd = NULL;
5312 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5314 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5316 (*secdesc_ctr)->sd->group_sid,
5317 (*secdesc_ctr)->sd->sacl,
5318 (*secdesc_ctr)->sd->dacl,
5325 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5326 if (!new_secdesc_ctr) {
5330 /* Swap with other one */
5332 *secdesc_ctr = new_secdesc_ctr;
5336 nt_printing_setsec(sharename, *secdesc_ctr);
5340 if (DEBUGLEVEL >= 10) {
5341 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5344 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5345 sharename, the_acl->num_aces));
5347 for (i = 0; i < the_acl->num_aces; i++) {
5350 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5352 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5353 the_acl->aces[i].type, the_acl->aces[i].flags,
5354 the_acl->aces[i].access_mask));
5363 1: level not implemented
5364 2: file doesn't exist
5365 3: can't allocate memory
5366 4: can't free memory
5367 5: non existant struct
5371 A printer and a printer driver are 2 different things.
5372 NT manages them separatelly, Samba does the same.
5373 Why ? Simply because it's easier and it makes sense !
5375 Now explanation: You have 3 printers behind your samba server,
5376 2 of them are the same make and model (laser A and B). But laser B
5377 has an 3000 sheet feeder and laser A doesn't such an option.
5378 Your third printer is an old dot-matrix model for the accounting :-).
5380 If the /usr/local/samba/lib directory (default dir), you will have
5381 5 files to describe all of this.
5383 3 files for the printers (1 by printer):
5386 NTprinter_accounting
5387 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5388 NTdriver_printer model X
5389 NTdriver_printer model Y
5391 jfm: I should use this comment for the text file to explain
5392 same thing for the forms BTW.
5393 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5397 /* Convert generic access rights to printer object specific access rights.
5398 It turns out that NT4 security descriptors use generic access rights and
5399 NT5 the object specific ones. */
5401 void map_printer_permissions(SEC_DESC *sd)
5405 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5406 se_map_generic(&sd->dacl->aces[i].access_mask,
5407 &printer_generic_mapping);
5411 /****************************************************************************
5412 Check a user has permissions to perform the given operation. We use the
5413 permission constants defined in include/rpc_spoolss.h to check the various
5414 actions we perform when checking printer access.
5416 PRINTER_ACCESS_ADMINISTER:
5417 print_queue_pause, print_queue_resume, update_printer_sec,
5418 update_printer, spoolss_addprinterex_level_2,
5419 _spoolss_setprinterdata
5424 JOB_ACCESS_ADMINISTER:
5425 print_job_delete, print_job_pause, print_job_resume,
5428 Try access control in the following order (for performance reasons):
5429 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5430 2) check security descriptor (bit comparisons in memory)
5431 3) "printer admins" (may result in numerous calls to winbind)
5433 ****************************************************************************/
5434 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5436 SEC_DESC_BUF *secdesc = NULL;
5437 uint32 access_granted;
5441 TALLOC_CTX *mem_ctx = NULL;
5442 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5444 /* If user is NULL then use the current_user structure */
5447 user = ¤t_user;
5449 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5451 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5455 /* Get printer name */
5457 pname = PRINTERNAME(snum);
5459 if (!pname || !*pname) {
5464 /* Get printer security descriptor */
5466 if(!(mem_ctx = talloc_init("print_access_check"))) {
5471 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5472 talloc_destroy(mem_ctx);
5477 if (access_type == JOB_ACCESS_ADMINISTER) {
5478 SEC_DESC_BUF *parent_secdesc = secdesc;
5480 /* Create a child security descriptor to check permissions
5481 against. This is because print jobs are child objects
5482 objects of a printer. */
5484 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5487 talloc_destroy(mem_ctx);
5492 /* Now this is the bit that really confuses me. The access
5493 type needs to be changed from JOB_ACCESS_ADMINISTER to
5494 PRINTER_ACCESS_ADMINISTER for this to work. Something
5495 to do with the child (job) object becoming like a
5498 access_type = PRINTER_ACCESS_ADMINISTER;
5503 map_printer_permissions(secdesc->sd);
5505 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5506 &access_granted, &status);
5508 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5510 /* see if we need to try the printer admin list */
5512 if ((access_granted == 0) &&
5513 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5514 user->nt_user_token,
5515 lp_printer_admin(snum)))) {
5516 talloc_destroy(mem_ctx);
5520 talloc_destroy(mem_ctx);
5529 /****************************************************************************
5530 Check the time parameters allow a print operation.
5531 *****************************************************************************/
5533 BOOL print_time_access_check(const char *servicename)
5535 NT_PRINTER_INFO_LEVEL *printer = NULL;
5537 time_t now = time(NULL);
5541 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5544 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5548 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5550 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5553 free_a_printer(&printer, 2);
5561 /****************************************************************************
5562 Fill in the servername sent in the _spoolss_open_printer_ex() call
5563 ****************************************************************************/
5565 char* get_server_name( Printer_entry *printer )
5567 return printer->servername;