2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern struct current_user current_user;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
53 STANDARD_MAPPING printer_std_mapping = {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
69 STANDARD_MAPPING printserver_std_mapping = {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
202 const char *long_archi;
203 const char *short_archi;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
212 #define SPL_ARCH_IA64 "IA64"
213 #define SPL_ARCH_X64 "x64"
215 static const struct table_node archi_table[]= {
217 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
218 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
219 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
220 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
221 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
222 {"Windows IA64", SPL_ARCH_IA64, 3 },
223 {"Windows x64", SPL_ARCH_X64, 3 },
228 /****************************************************************************
229 generate a new TDB_DATA key for storing a printer
230 ****************************************************************************/
232 static TDB_DATA make_printer_tdbkey( const char *sharename )
235 static pstring keystr;
238 fstrcpy( share, sharename );
241 pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
243 key = string_term_tdb_data(keystr);
248 /****************************************************************************
249 generate a new TDB_DATA key for storing a printer security descriptor
250 ****************************************************************************/
252 static TDB_DATA make_printers_secdesc_tdbkey( const char* sharename )
255 static pstring keystr;
258 fstrcpy( share, sharename );
261 pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
263 key = string_term_tdb_data(keystr);
268 /****************************************************************************
269 ****************************************************************************/
271 static BOOL upgrade_to_version_3(void)
273 TDB_DATA kbuf, newkey, dbuf;
275 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
277 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
278 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
280 dbuf = tdb_fetch(tdb_drivers, kbuf);
282 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
283 DEBUG(0,("upgrade_to_version_3:moving form\n"));
284 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
285 SAFE_FREE(dbuf.dptr);
286 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
289 if (tdb_delete(tdb_drivers, kbuf) != 0) {
290 SAFE_FREE(dbuf.dptr);
291 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
296 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
297 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
298 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
299 SAFE_FREE(dbuf.dptr);
300 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
303 if (tdb_delete(tdb_drivers, kbuf) != 0) {
304 SAFE_FREE(dbuf.dptr);
305 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
310 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
311 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
312 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
313 SAFE_FREE(dbuf.dptr);
314 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
317 if (tdb_delete(tdb_drivers, kbuf) != 0) {
318 SAFE_FREE(dbuf.dptr);
319 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
324 SAFE_FREE(dbuf.dptr);
330 /*******************************************************************
331 Fix an issue with security descriptors. Printer sec_desc must
332 use more than the generic bits that were previously used
333 in <= 3.0.14a. They must also have a owner and group SID assigned.
334 Otherwise, any printers than have been migrated to a Windows
335 host using printmig.exe will not be accessible.
336 *******************************************************************/
338 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
339 TDB_DATA data, void *state )
342 SEC_DESC_BUF *sd_orig = NULL;
343 SEC_DESC_BUF *sd_new, *sd_store;
344 SEC_DESC *sec, *new_sec;
345 TALLOC_CTX *ctx = state;
351 if (!data.dptr || data.dsize == 0) {
355 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
359 /* upgrade the security descriptor */
363 prs_init( &ps, 0, ctx, UNMARSHALL );
364 prs_give_memory( &ps, data.dptr, data.dsize, False );
366 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
367 /* delete bad entries */
368 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", 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 = 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( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
493 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
495 else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
496 new_key = make_printers_secdesc_tdbkey( 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(void)
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 message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer, NULL);
636 * register callback to handle updating printer data
637 * when a driver is initialized
640 message_register(MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata,
643 /* of course, none of the message callbacks matter if you don't
644 tell messages.c that you interested in receiving PRINT_GENERAL
645 msgs. This is done in claim_connection() */
648 if ( lp_security() == SEC_ADS ) {
649 win_rc = check_published_printers();
650 if (!W_ERROR_IS_OK(win_rc))
651 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
657 /*******************************************************************
658 Function to allow filename parsing "the old way".
659 ********************************************************************/
661 static void driver_unix_convert(char *name,connection_struct *conn,
662 char *saved_last_component, SMB_STRUCT_STAT *pst)
665 unix_clean_name(name);
666 trim_string(name,"/","/");
667 unix_convert(conn, name, False, saved_last_component, pst);
670 /*******************************************************************
671 tdb traversal function for counting printers.
672 ********************************************************************/
674 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
675 TDB_DATA data, void *context)
677 int *printer_count = (int*)context;
679 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
681 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
687 /*******************************************************************
688 Update the spooler global c_setprinter. This variable is initialized
689 when the parent smbd starts with the number of existing printers. It
690 is monotonically increased by the current number of printers *after*
691 each add or delete printer RPC. Only Microsoft knows why... JRR020119
692 ********************************************************************/
694 uint32 update_c_setprinter(BOOL initialize)
697 int32 printer_count = 0;
699 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
701 /* Traverse the tdb, counting the printers */
702 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
704 /* If initializing, set c_setprinter to current printers count
705 * otherwise, bump it by the current printer count
708 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
710 c_setprinter = printer_count;
712 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
713 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
715 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
717 return (uint32)c_setprinter;
720 /*******************************************************************
721 Get the spooler global c_setprinter, accounting for initialization.
722 ********************************************************************/
724 uint32 get_c_setprinter(void)
726 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
728 if (c_setprinter == (int32)-1)
729 c_setprinter = update_c_setprinter(True);
731 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
733 return (uint32)c_setprinter;
736 /****************************************************************************
737 Get builtin form struct list.
738 ****************************************************************************/
740 int get_builtin_ntforms(nt_forms_struct **list)
742 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
746 return sizeof(default_forms) / sizeof(default_forms[0]);
749 /****************************************************************************
750 get a builtin form struct
751 ****************************************************************************/
753 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
757 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
758 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
759 count = sizeof(default_forms) / sizeof(default_forms[0]);
760 for (i=0;i<count;i++) {
761 if (strequal(form_name,default_forms[i].name)) {
762 DEBUGADD(6,("Found builtin form %s \n", form_name));
763 memcpy(form,&default_forms[i],sizeof(*form));
771 /****************************************************************************
772 get a form struct list.
773 ****************************************************************************/
775 int get_ntforms(nt_forms_struct **list)
777 TDB_DATA kbuf, newkey, dbuf;
778 nt_forms_struct form;
785 for (kbuf = tdb_firstkey(tdb_forms);
787 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
789 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
792 dbuf = tdb_fetch(tdb_forms, kbuf);
796 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
797 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
798 &i, &form.flag, &form.width, &form.length, &form.left,
799 &form.top, &form.right, &form.bottom);
800 SAFE_FREE(dbuf.dptr);
801 if (ret != dbuf.dsize)
804 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
806 DEBUG(0,("get_ntforms: Realloc fail.\n"));
817 /****************************************************************************
818 write a form struct list
819 ****************************************************************************/
820 int write_ntforms(nt_forms_struct **list, int number)
827 for (i=0;i<number;i++) {
828 /* save index, so list is rebuilt in correct order */
829 len = tdb_pack(buf, sizeof(buf), "dddddddd",
830 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
831 (*list)[i].left, (*list)[i].top, (*list)[i].right,
833 if (len > sizeof(buf)) break;
834 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
837 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) break;
843 /****************************************************************************
844 add a form struct at the end of the list
845 ****************************************************************************/
846 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
853 * NT tries to add forms even when
854 * they are already in the base
855 * only update the values if already present
860 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
861 for (n=0; n<*count; n++) {
862 if ( strequal((*list)[n].name, form_name) ) {
869 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
870 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
873 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
877 (*list)[n].flag=form->flags;
878 (*list)[n].width=form->size_x;
879 (*list)[n].length=form->size_y;
880 (*list)[n].left=form->left;
881 (*list)[n].top=form->top;
882 (*list)[n].right=form->right;
883 (*list)[n].bottom=form->bottom;
885 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
886 update ? "updated" : "added", form_name));
891 /****************************************************************************
892 Delete a named form struct.
893 ****************************************************************************/
895 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
903 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
905 for (n=0; n<*count; n++) {
906 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
907 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
913 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
914 *ret = WERR_INVALID_PARAM;
918 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
919 if (tdb_delete_bystring(tdb_forms, key) != 0) {
927 /****************************************************************************
928 Update a form struct.
929 ****************************************************************************/
931 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
935 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
937 DEBUG(106, ("[%s]\n", form_name));
938 for (n=0; n<count; n++) {
939 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
940 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
944 if (n==count) return;
946 (*list)[n].flag=form->flags;
947 (*list)[n].width=form->size_x;
948 (*list)[n].length=form->size_y;
949 (*list)[n].left=form->left;
950 (*list)[n].top=form->top;
951 (*list)[n].right=form->right;
952 (*list)[n].bottom=form->bottom;
955 /****************************************************************************
956 Get the nt drivers list.
957 Traverse the database and look-up the matching names.
958 ****************************************************************************/
959 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
962 const char *short_archi;
964 TDB_DATA kbuf, newkey;
966 short_archi = get_short_archi(architecture);
971 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
973 for (kbuf = tdb_firstkey(tdb_drivers);
975 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
977 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
980 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
981 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
985 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
992 /****************************************************************************
993 Function to do the mapping between the long architecture name and
995 ****************************************************************************/
997 const char *get_short_archi(const char *long_archi)
1001 DEBUG(107,("Getting architecture dependant directory\n"));
1004 } while ( (archi_table[i].long_archi!=NULL ) &&
1005 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1007 if (archi_table[i].long_archi==NULL) {
1008 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1012 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1014 DEBUGADD(108,("index: [%d]\n", i));
1015 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1016 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1018 return archi_table[i].short_archi;
1021 /****************************************************************************
1022 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1023 There are two case to be covered here: PE (Portable Executable) and NE (New
1024 Executable) files. Both files support the same INFO structure, but PE files
1025 store the signature in unicode, and NE files store it as !unicode.
1026 returns -1 on error, 1 on version info found, and 0 on no version info found.
1027 ****************************************************************************/
1029 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1035 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1036 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1037 fname, DOS_HEADER_SIZE));
1041 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1042 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1043 fname, (unsigned long)byte_count));
1044 goto no_version_info;
1047 /* Is this really a DOS header? */
1048 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1049 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1050 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1051 goto no_version_info;
1054 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1055 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1056 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1058 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1059 goto no_version_info;
1062 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1063 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1064 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1065 fname, (unsigned long)byte_count));
1066 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1067 goto no_version_info;
1070 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1071 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1072 unsigned int num_sections;
1073 unsigned int section_table_bytes;
1075 /* Just skip over optional header to get to section table */
1076 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
1077 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1078 SEEK_CUR) == (SMB_OFF_T)-1) {
1079 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1084 /* get the section table */
1085 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1086 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1087 if (section_table_bytes == 0)
1091 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1092 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1093 fname, section_table_bytes));
1097 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1098 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1099 fname, (unsigned long)byte_count));
1103 /* Iterate the section table looking for the resource section ".rsrc" */
1104 for (i = 0; i < num_sections; i++) {
1105 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1107 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1108 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1109 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1111 if (section_bytes == 0)
1115 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1116 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1117 fname, section_bytes));
1121 /* Seek to the start of the .rsrc section info */
1122 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1123 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1128 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1129 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1130 fname, (unsigned long)byte_count));
1134 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1137 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1138 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1139 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1140 /* Align to next long address */
1141 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1143 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1144 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1145 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1147 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1148 fname, *major, *minor,
1149 (*major>>16)&0xffff, *major&0xffff,
1150 (*minor>>16)&0xffff, *minor&0xffff));
1159 /* Version info not found, fall back to origin date/time */
1160 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1164 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1165 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1166 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1167 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1168 /* At this point, we assume the file is in error. It still could be somthing
1169 * else besides a NE file, but it unlikely at this point. */
1173 /* Allocate a bit more space to speed up things */
1175 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1176 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1177 fname, PE_HEADER_SIZE));
1181 /* This is a HACK! I got tired of trying to sort through the messy
1182 * 'NE' file format. If anyone wants to clean this up please have at
1183 * it, but this works. 'NE' files will eventually fade away. JRR */
1184 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1185 /* Cover case that should not occur in a well formed 'NE' .dll file */
1186 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1188 for(i=0; i<byte_count; i++) {
1189 /* Fast skip past data that can't possibly match */
1190 if (buf[i] != 'V') continue;
1192 /* Potential match data crosses buf boundry, move it to beginning
1193 * of buf, and fill the buf with as much as it will hold. */
1194 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1197 memcpy(buf, &buf[i], byte_count-i);
1198 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1199 (byte_count-i))) < 0) {
1201 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1206 byte_count = bc + (byte_count - i);
1207 if (byte_count<VS_VERSION_INFO_SIZE) break;
1212 /* Check that the full signature string and the magic number that
1213 * follows exist (not a perfect solution, but the chances that this
1214 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1215 * twice, as it is simpler to read the code. */
1216 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1217 /* Compute skip alignment to next long address */
1218 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1219 sizeof(VS_SIGNATURE)) & 3;
1220 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1222 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1223 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1224 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1225 fname, *major, *minor,
1226 (*major>>16)&0xffff, *major&0xffff,
1227 (*minor>>16)&0xffff, *minor&0xffff));
1234 /* Version info not found, fall back to origin date/time */
1235 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1240 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1241 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1242 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1253 /****************************************************************************
1254 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1255 share one or more files. During the MS installation process files are checked
1256 to insure that only a newer version of a shared file is installed over an
1257 older version. There are several possibilities for this comparison. If there
1258 is no previous version, the new one is newer (obviously). If either file is
1259 missing the version info structure, compare the creation date (on Unix use
1260 the modification date). Otherwise chose the numerically larger version number.
1261 ****************************************************************************/
1263 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1265 BOOL use_version = True;
1270 time_t new_create_time;
1274 time_t old_create_time;
1276 files_struct *fsp = NULL;
1278 SMB_STRUCT_STAT stat_buf;
1282 SET_STAT_INVALID(st);
1283 SET_STAT_INVALID(stat_buf);
1284 new_create_time = (time_t)0;
1285 old_create_time = (time_t)0;
1287 /* Get file version info (if available) for previous file (if it exists) */
1288 pstrcpy(filepath, old_file);
1290 driver_unix_convert(filepath,conn,NULL,&stat_buf);
1292 status = open_file_ntcreate(conn, filepath, &stat_buf,
1294 FILE_SHARE_READ|FILE_SHARE_WRITE,
1297 FILE_ATTRIBUTE_NORMAL,
1301 if (!NT_STATUS_IS_OK(status)) {
1302 /* Old file not found, so by definition new file is in fact newer */
1303 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1308 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1314 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1316 use_version = False;
1317 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1318 old_create_time = st.st_mtime;
1319 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1322 close_file(fsp, NORMAL_CLOSE);
1324 /* Get file version info (if available) for new file */
1325 pstrcpy(filepath, new_file);
1326 driver_unix_convert(filepath,conn,NULL,&stat_buf);
1328 status = open_file_ntcreate(conn, filepath, &stat_buf,
1330 FILE_SHARE_READ|FILE_SHARE_WRITE,
1333 FILE_ATTRIBUTE_NORMAL,
1337 if (!NT_STATUS_IS_OK(status)) {
1338 /* New file not found, this shouldn't occur if the caller did its job */
1339 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1344 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1350 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1352 use_version = False;
1353 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1354 new_create_time = st.st_mtime;
1355 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1358 close_file(fsp, NORMAL_CLOSE);
1360 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1361 /* Compare versions and choose the larger version number */
1362 if (new_major > old_major ||
1363 (new_major == old_major && new_minor > old_minor)) {
1365 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1369 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1374 /* Compare modification time/dates and choose the newest time/date */
1375 if (new_create_time > old_create_time) {
1376 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1380 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1387 close_file(fsp, NORMAL_CLOSE);
1391 /****************************************************************************
1392 Determine the correct cVersion associated with an architecture and driver
1393 ****************************************************************************/
1394 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1395 struct current_user *user, WERROR *perr)
1402 files_struct *fsp = NULL;
1404 connection_struct *conn;
1407 SET_STAT_INVALID(st);
1409 *perr = WERR_INVALID_PARAM;
1411 /* If architecture is Windows 95/98/ME, the version is always 0. */
1412 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1413 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1418 /* If architecture is Windows x64, the version is always 3. */
1419 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1420 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1426 * Connect to the print$ share under the same account as the user connected
1427 * to the rpc pipe. Note we must still be root to do this.
1430 /* Null password is ok - we are already an authenticated user... */
1431 null_pw = data_blob(NULL, 0);
1432 fstrcpy(res_type, "A:");
1434 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1438 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1439 *perr = ntstatus_to_werror(nt_status);
1443 /* We are temporarily becoming the connection user. */
1444 if (!become_user(conn, user->vuid)) {
1445 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1446 *perr = WERR_ACCESS_DENIED;
1450 /* Open the driver file (Portable Executable format) and determine the
1451 * deriver the cversion. */
1452 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1454 driver_unix_convert(driverpath,conn,NULL,&st);
1456 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1457 *perr = WERR_BADFILE;
1461 status = open_file_ntcreate(conn, driverpath, &st,
1463 FILE_SHARE_READ|FILE_SHARE_WRITE,
1466 FILE_ATTRIBUTE_NORMAL,
1470 if (!NT_STATUS_IS_OK(status)) {
1471 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1472 driverpath, errno));
1473 *perr = WERR_ACCESS_DENIED;
1478 int ret = get_file_version(fsp, driverpath, &major, &minor);
1479 if (ret == -1) goto error_exit;
1482 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1487 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1488 * for more details. Version in this case is not just the version of the
1489 * file, but the version in the sense of kernal mode (2) vs. user mode
1490 * (3) drivers. Other bits of the version fields are the version info.
1493 cversion = major & 0x0000ffff;
1495 case 2: /* WinNT drivers */
1496 case 3: /* Win2K drivers */
1500 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1501 driverpath, cversion));
1505 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1506 driverpath, major, minor));
1509 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1510 driverpath, cversion));
1512 close_file(fsp, NORMAL_CLOSE);
1513 close_cnum(conn, user->vuid);
1522 close_file(fsp, NORMAL_CLOSE);
1524 close_cnum(conn, user->vuid);
1529 /****************************************************************************
1530 ****************************************************************************/
1531 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1532 struct current_user *user)
1534 const char *architecture;
1540 /* clean up the driver name.
1541 * we can get .\driver.dll
1542 * or worse c:\windows\system\driver.dll !
1544 /* using an intermediate string to not have overlaping memcpy()'s */
1545 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1546 fstrcpy(new_name, p+1);
1547 fstrcpy(driver->driverpath, new_name);
1550 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1551 fstrcpy(new_name, p+1);
1552 fstrcpy(driver->datafile, new_name);
1555 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1556 fstrcpy(new_name, p+1);
1557 fstrcpy(driver->configfile, new_name);
1560 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1561 fstrcpy(new_name, p+1);
1562 fstrcpy(driver->helpfile, new_name);
1565 if (driver->dependentfiles) {
1566 for (i=0; *driver->dependentfiles[i]; i++) {
1567 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1568 fstrcpy(new_name, p+1);
1569 fstrcpy(driver->dependentfiles[i], new_name);
1574 architecture = get_short_archi(driver->environment);
1575 if (!architecture) {
1576 return WERR_UNKNOWN_PRINTER_DRIVER;
1579 /* jfm:7/16/2000 the client always sends the cversion=0.
1580 * The server should check which version the driver is by reading
1581 * the PE header of driver->driverpath.
1583 * For Windows 95/98 the version is 0 (so the value sent is correct)
1584 * For Windows NT (the architecture doesn't matter)
1585 * NT 3.1: cversion=0
1586 * NT 3.5/3.51: cversion=1
1590 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1596 /****************************************************************************
1597 ****************************************************************************/
1598 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1600 const char *architecture;
1606 /* clean up the driver name.
1607 * we can get .\driver.dll
1608 * or worse c:\windows\system\driver.dll !
1610 /* using an intermediate string to not have overlaping memcpy()'s */
1611 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1612 fstrcpy(new_name, p+1);
1613 fstrcpy(driver->driverpath, new_name);
1616 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1617 fstrcpy(new_name, p+1);
1618 fstrcpy(driver->datafile, new_name);
1621 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1622 fstrcpy(new_name, p+1);
1623 fstrcpy(driver->configfile, new_name);
1626 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1627 fstrcpy(new_name, p+1);
1628 fstrcpy(driver->helpfile, new_name);
1631 if (driver->dependentfiles) {
1632 for (i=0; *driver->dependentfiles[i]; i++) {
1633 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1634 fstrcpy(new_name, p+1);
1635 fstrcpy(driver->dependentfiles[i], new_name);
1640 architecture = get_short_archi(driver->environment);
1641 if (!architecture) {
1642 return WERR_UNKNOWN_PRINTER_DRIVER;
1645 /* jfm:7/16/2000 the client always sends the cversion=0.
1646 * The server should check which version the driver is by reading
1647 * the PE header of driver->driverpath.
1649 * For Windows 95/98 the version is 0 (so the value sent is correct)
1650 * For Windows NT (the architecture doesn't matter)
1651 * NT 3.1: cversion=0
1652 * NT 3.5/3.51: cversion=1
1657 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1663 /****************************************************************************
1664 ****************************************************************************/
1665 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1666 uint32 level, struct current_user *user)
1671 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1672 driver=driver_abstract.info_3;
1673 return clean_up_driver_struct_level_3(driver, user);
1677 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1678 driver=driver_abstract.info_6;
1679 return clean_up_driver_struct_level_6(driver, user);
1682 return WERR_INVALID_PARAM;
1686 /****************************************************************************
1687 This function sucks and should be replaced. JRA.
1688 ****************************************************************************/
1690 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1692 dst->cversion = src->version;
1694 fstrcpy( dst->name, src->name);
1695 fstrcpy( dst->environment, src->environment);
1696 fstrcpy( dst->driverpath, src->driverpath);
1697 fstrcpy( dst->datafile, src->datafile);
1698 fstrcpy( dst->configfile, src->configfile);
1699 fstrcpy( dst->helpfile, src->helpfile);
1700 fstrcpy( dst->monitorname, src->monitorname);
1701 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1702 dst->dependentfiles = src->dependentfiles;
1705 #if 0 /* Debugging function */
1707 static char* ffmt(unsigned char *c){
1709 static char ffmt_str[17];
1711 for (i=0; i<16; i++) {
1712 if ((c[i] < ' ') || (c[i] > '~'))
1723 /****************************************************************************
1724 ****************************************************************************/
1725 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1726 struct current_user *user, WERROR *perr)
1728 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1729 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1730 const char *architecture;
1735 connection_struct *conn;
1744 memset(inbuf, '\0', sizeof(inbuf));
1745 memset(outbuf, '\0', sizeof(outbuf));
1749 driver=driver_abstract.info_3;
1750 else if (level==6) {
1751 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1752 driver = &converted_driver;
1754 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1755 return WERR_UNKNOWN_LEVEL;
1758 architecture = get_short_archi(driver->environment);
1759 if (!architecture) {
1760 return WERR_UNKNOWN_PRINTER_DRIVER;
1764 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1765 * Note we must be root to do this.
1768 null_pw = data_blob(NULL, 0);
1769 fstrcpy(res_type, "A:");
1771 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1775 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1776 *perr = ntstatus_to_werror(nt_status);
1777 return WERR_NO_SUCH_SHARE;
1781 * Save who we are - we are temporarily becoming the connection user.
1784 if (!become_user(conn, conn->vuid)) {
1785 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1786 return WERR_ACCESS_DENIED;
1790 * make the directories version and version\driver_name
1791 * under the architecture directory.
1793 DEBUG(5,("Creating first directory\n"));
1794 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1795 driver_unix_convert(new_dir, conn, NULL, &st);
1796 create_directory(conn, new_dir);
1798 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1799 * listed for this driver which has already been moved, skip it (note:
1800 * drivers may list the same file name several times. Then check if the
1801 * file already exists in archi\cversion\, if so, check that the version
1802 * info (or time stamps if version info is unavailable) is newer (or the
1803 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1804 * Otherwise, delete the file.
1806 * If a file is not moved to archi\cversion\ because of an error, all the
1807 * rest of the 'unmoved' driver files are removed from archi\. If one or
1808 * more of the driver's files was already moved to archi\cversion\, it
1809 * potentially leaves the driver in a partially updated state. Version
1810 * trauma will most likely occur if an client attempts to use any printer
1811 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1812 * done is appropriate... later JRR
1815 DEBUG(5,("Moving files now !\n"));
1817 if (driver->driverpath && strlen(driver->driverpath)) {
1818 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1819 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1820 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1821 driver_unix_convert(new_name, conn, NULL, &st);
1822 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1823 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1824 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1825 new_name, old_name));
1826 *perr = WERR_ACCESS_DENIED;
1832 if (driver->datafile && strlen(driver->datafile)) {
1833 if (!strequal(driver->datafile, driver->driverpath)) {
1834 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1835 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1836 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1837 driver_unix_convert(new_name, conn, NULL, &st);
1838 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1839 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1840 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1841 new_name, old_name));
1842 *perr = WERR_ACCESS_DENIED;
1849 if (driver->configfile && strlen(driver->configfile)) {
1850 if (!strequal(driver->configfile, driver->driverpath) &&
1851 !strequal(driver->configfile, driver->datafile)) {
1852 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1853 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1854 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1855 driver_unix_convert(new_name, conn, NULL, &st);
1856 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1857 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1858 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1859 new_name, old_name));
1860 *perr = WERR_ACCESS_DENIED;
1867 if (driver->helpfile && strlen(driver->helpfile)) {
1868 if (!strequal(driver->helpfile, driver->driverpath) &&
1869 !strequal(driver->helpfile, driver->datafile) &&
1870 !strequal(driver->helpfile, driver->configfile)) {
1871 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1872 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1873 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1874 driver_unix_convert(new_name, conn, NULL, &st);
1875 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1876 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1877 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1878 new_name, old_name));
1879 *perr = WERR_ACCESS_DENIED;
1886 if (driver->dependentfiles) {
1887 for (i=0; *driver->dependentfiles[i]; i++) {
1888 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1889 !strequal(driver->dependentfiles[i], driver->datafile) &&
1890 !strequal(driver->dependentfiles[i], driver->configfile) &&
1891 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1893 for (j=0; j < i; j++) {
1894 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1899 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1900 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1901 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1902 driver_unix_convert(new_name, conn, NULL, &st);
1903 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
1904 OPENX_FILE_EXISTS_TRUNCATE|
1905 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1906 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1907 new_name, old_name));
1908 *perr = WERR_ACCESS_DENIED;
1917 close_cnum(conn, user->vuid);
1920 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1923 /****************************************************************************
1924 ****************************************************************************/
1925 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1928 const char *architecture;
1936 architecture = get_short_archi(driver->environment);
1937 if (!architecture) {
1941 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1942 * \\server is added in the rpc server layer.
1943 * It does make sense to NOT store the server's name in the printer TDB.
1946 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1948 /* .inf files do not always list a file for each of the four standard files.
1949 * Don't prepend a path to a null filename, or client claims:
1950 * "The server on which the printer resides does not have a suitable
1951 * <printer driver name> printer driver installed. Click OK if you
1952 * wish to install the driver on your local machine."
1954 if (strlen(driver->driverpath)) {
1955 fstrcpy(temp_name, driver->driverpath);
1956 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1959 if (strlen(driver->datafile)) {
1960 fstrcpy(temp_name, driver->datafile);
1961 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1964 if (strlen(driver->configfile)) {
1965 fstrcpy(temp_name, driver->configfile);
1966 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1969 if (strlen(driver->helpfile)) {
1970 fstrcpy(temp_name, driver->helpfile);
1971 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1974 if (driver->dependentfiles) {
1975 for (i=0; *driver->dependentfiles[i]; i++) {
1976 fstrcpy(temp_name, driver->dependentfiles[i]);
1977 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1981 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1983 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1990 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1993 driver->environment,
1998 driver->monitorname,
1999 driver->defaultdatatype);
2001 if (driver->dependentfiles) {
2002 for (i=0; *driver->dependentfiles[i]; i++) {
2003 len += tdb_pack(buf+len, buflen-len, "f",
2004 driver->dependentfiles[i]);
2008 if (len != buflen) {
2009 buf = (char *)SMB_REALLOC(buf, len);
2011 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2022 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2026 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2032 /****************************************************************************
2033 ****************************************************************************/
2034 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2036 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2039 info3.cversion = driver->version;
2040 fstrcpy(info3.name,driver->name);
2041 fstrcpy(info3.environment,driver->environment);
2042 fstrcpy(info3.driverpath,driver->driverpath);
2043 fstrcpy(info3.datafile,driver->datafile);
2044 fstrcpy(info3.configfile,driver->configfile);
2045 fstrcpy(info3.helpfile,driver->helpfile);
2046 fstrcpy(info3.monitorname,driver->monitorname);
2047 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2048 info3.dependentfiles = driver->dependentfiles;
2050 return add_a_printer_driver_3(&info3);
2054 /****************************************************************************
2055 ****************************************************************************/
2056 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2058 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2062 fstrcpy(info.name, driver);
2063 fstrcpy(info.defaultdatatype, "RAW");
2065 fstrcpy(info.driverpath, "");
2066 fstrcpy(info.datafile, "");
2067 fstrcpy(info.configfile, "");
2068 fstrcpy(info.helpfile, "");
2070 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2073 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2074 fstrcpy(info.dependentfiles[0], "");
2076 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2078 SAFE_FREE(info.dependentfiles);
2085 /****************************************************************************
2086 ****************************************************************************/
2087 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2089 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2091 const char *architecture;
2096 ZERO_STRUCT(driver);
2098 architecture = get_short_archi(arch);
2099 if ( !architecture ) {
2100 return WERR_UNKNOWN_PRINTER_DRIVER;
2103 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2105 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2108 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2110 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2112 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2114 return WERR_UNKNOWN_PRINTER_DRIVER;
2116 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2125 driver.defaultdatatype);
2128 while (len < dbuf.dsize) {
2129 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2130 if ( !driver.dependentfiles ) {
2131 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2135 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2136 &driver.dependentfiles[i]);
2140 if ( driver.dependentfiles )
2141 fstrcpy( driver.dependentfiles[i], "" );
2143 SAFE_FREE(dbuf.dptr);
2145 if (len != dbuf.dsize) {
2146 SAFE_FREE(driver.dependentfiles);
2148 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2151 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2153 SAFE_FREE(driver.dependentfiles);
2160 /****************************************************************************
2161 Debugging function, dump at level 6 the struct in the logs.
2162 ****************************************************************************/
2164 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2167 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2170 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2176 if (driver.info_3 == NULL)
2179 info3=driver.info_3;
2181 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2182 DEBUGADD(20,("name:[%s]\n", info3->name));
2183 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2184 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2185 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2186 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2187 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2188 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2189 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2191 for (i=0; info3->dependentfiles &&
2192 *info3->dependentfiles[i]; i++) {
2193 DEBUGADD(20,("dependentfile:[%s]\n",
2194 info3->dependentfiles[i]));
2201 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2209 /****************************************************************************
2210 ****************************************************************************/
2211 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2215 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2220 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2221 nt_devmode->devicename,
2222 nt_devmode->formname,
2224 nt_devmode->specversion,
2225 nt_devmode->driverversion,
2227 nt_devmode->driverextra,
2228 nt_devmode->orientation,
2229 nt_devmode->papersize,
2230 nt_devmode->paperlength,
2231 nt_devmode->paperwidth,
2234 nt_devmode->defaultsource,
2235 nt_devmode->printquality,
2238 nt_devmode->yresolution,
2239 nt_devmode->ttoption,
2240 nt_devmode->collate,
2241 nt_devmode->logpixels,
2244 nt_devmode->bitsperpel,
2245 nt_devmode->pelswidth,
2246 nt_devmode->pelsheight,
2247 nt_devmode->displayflags,
2248 nt_devmode->displayfrequency,
2249 nt_devmode->icmmethod,
2250 nt_devmode->icmintent,
2251 nt_devmode->mediatype,
2252 nt_devmode->dithertype,
2253 nt_devmode->reserved1,
2254 nt_devmode->reserved2,
2255 nt_devmode->panningwidth,
2256 nt_devmode->panningheight,
2257 nt_devmode->nt_dev_private);
2260 if (nt_devmode->nt_dev_private) {
2261 len += tdb_pack(buf+len, buflen-len, "B",
2262 nt_devmode->driverextra,
2263 nt_devmode->nt_dev_private);
2266 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2271 /****************************************************************************
2272 Pack all values in all printer keys
2273 ***************************************************************************/
2275 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2279 REGISTRY_VALUE *val;
2280 REGVAL_CTR *val_ctr;
2287 /* loop over all keys */
2289 for ( i=0; i<data->num_keys; i++ ) {
2290 val_ctr = data->keys[i].values;
2291 num_values = regval_ctr_numvals( val_ctr );
2293 /* pack the keyname followed by a empty value */
2295 len += tdb_pack(buf+len, buflen-len, "pPdB",
2296 &data->keys[i].name,
2302 /* now loop over all values */
2304 for ( j=0; j<num_values; j++ ) {
2305 /* pathname should be stored as <key>\<value> */
2307 val = regval_ctr_specific_value( val_ctr, j );
2308 pstrcpy( path, data->keys[i].name );
2309 pstrcat( path, "\\" );
2310 pstrcat( path, regval_name(val) );
2312 len += tdb_pack(buf+len, buflen-len, "pPdB",
2317 regval_data_p(val) );
2319 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2326 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2332 /****************************************************************************
2333 Delete a printer - this just deletes the printer info file, any open
2334 handles are not affected.
2335 ****************************************************************************/
2337 uint32 del_a_printer(const char *sharename)
2340 pstring printdb_path;
2342 kbuf = make_printer_tdbkey( sharename );
2343 tdb_delete(tdb_printers, kbuf);
2345 kbuf= make_printers_secdesc_tdbkey( sharename );
2346 tdb_delete(tdb_printers, kbuf);
2348 close_all_print_db();
2350 if (geteuid() == 0) {
2351 pstrcpy(printdb_path, lock_path("printing/"));
2352 pstrcat(printdb_path, sharename);
2353 pstrcat(printdb_path, ".tdb");
2355 unlink(printdb_path);
2361 /****************************************************************************
2362 ****************************************************************************/
2363 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2368 TDB_DATA kbuf, dbuf;
2371 * in addprinter: no servername and the printer is the name
2372 * in setprinter: servername is \\server
2373 * and printer is \\server\\printer
2375 * Samba manages only local printers.
2376 * we currently don't support things like i
2377 * path=\\other_server\printer
2379 * We only store the printername, not \\server\printername
2382 if ( info->servername[0] != '\0' ) {
2383 trim_string(info->printername, info->servername, NULL);
2384 trim_char(info->printername, '\\', '\0');
2385 info->servername[0]='\0';
2389 * JFM: one day I'll forget.
2390 * below that's info->portname because that's the SAMBA sharename
2391 * and I made NT 'thinks' it's the portname
2392 * the info->sharename is the thing you can name when you add a printer
2393 * that's the short-name when you create shared printer for 95/98
2394 * So I've made a limitation in SAMBA: you can only have 1 printer model
2395 * behind a SAMBA share.
2403 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2406 info->default_priority,
2423 info->printprocessor,
2427 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2429 len += pack_values( info->data, buf+len, buflen-len );
2431 if (buflen != len) {
2432 buf = (char *)SMB_REALLOC(buf, len);
2434 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2443 kbuf = make_printer_tdbkey( info->sharename );
2448 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2451 if (!W_ERROR_IS_OK(ret))
2452 DEBUG(8, ("error updating printer to tdb on disk\n"));
2456 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2457 info->sharename, info->drivername, info->portname, len));
2463 /****************************************************************************
2464 Malloc and return an NT devicemode.
2465 ****************************************************************************/
2467 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2470 char adevice[MAXDEVICENAME];
2471 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2473 if (nt_devmode == NULL) {
2474 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2478 ZERO_STRUCTP(nt_devmode);
2480 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2481 fstrcpy(nt_devmode->devicename, adevice);
2483 fstrcpy(nt_devmode->formname, "Letter");
2485 nt_devmode->specversion = 0x0401;
2486 nt_devmode->driverversion = 0x0400;
2487 nt_devmode->size = 0x00DC;
2488 nt_devmode->driverextra = 0x0000;
2489 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2490 DEFAULTSOURCE | COPIES | SCALE |
2491 PAPERSIZE | ORIENTATION;
2492 nt_devmode->orientation = 1;
2493 nt_devmode->papersize = PAPER_LETTER;
2494 nt_devmode->paperlength = 0;
2495 nt_devmode->paperwidth = 0;
2496 nt_devmode->scale = 0x64;
2497 nt_devmode->copies = 1;
2498 nt_devmode->defaultsource = BIN_FORMSOURCE;
2499 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2500 nt_devmode->color = COLOR_MONOCHROME;
2501 nt_devmode->duplex = DUP_SIMPLEX;
2502 nt_devmode->yresolution = 0;
2503 nt_devmode->ttoption = TT_SUBDEV;
2504 nt_devmode->collate = COLLATE_FALSE;
2505 nt_devmode->icmmethod = 0;
2506 nt_devmode->icmintent = 0;
2507 nt_devmode->mediatype = 0;
2508 nt_devmode->dithertype = 0;
2510 /* non utilisés par un driver d'imprimante */
2511 nt_devmode->logpixels = 0;
2512 nt_devmode->bitsperpel = 0;
2513 nt_devmode->pelswidth = 0;
2514 nt_devmode->pelsheight = 0;
2515 nt_devmode->displayflags = 0;
2516 nt_devmode->displayfrequency = 0;
2517 nt_devmode->reserved1 = 0;
2518 nt_devmode->reserved2 = 0;
2519 nt_devmode->panningwidth = 0;
2520 nt_devmode->panningheight = 0;
2522 nt_devmode->nt_dev_private = NULL;
2526 /****************************************************************************
2527 Deepcopy an NT devicemode.
2528 ****************************************************************************/
2530 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2532 NT_DEVICEMODE *new_nt_devicemode = NULL;
2534 if ( !nt_devicemode )
2537 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2538 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2542 new_nt_devicemode->nt_dev_private = NULL;
2543 if (nt_devicemode->nt_dev_private != NULL) {
2544 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2545 SAFE_FREE(new_nt_devicemode);
2546 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2551 return new_nt_devicemode;
2554 /****************************************************************************
2555 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2556 ****************************************************************************/
2558 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2560 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2562 if(nt_devmode == NULL)
2565 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2567 SAFE_FREE(nt_devmode->nt_dev_private);
2568 SAFE_FREE(*devmode_ptr);
2571 /****************************************************************************
2572 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2573 ****************************************************************************/
2575 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2577 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2582 free_nt_devicemode(&info->devmode);
2584 TALLOC_FREE( *info_ptr );
2588 /****************************************************************************
2589 ****************************************************************************/
2590 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2594 NT_DEVICEMODE devmode;
2596 ZERO_STRUCT(devmode);
2598 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2600 if (!*nt_devmode) return len;
2602 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2606 &devmode.specversion,
2607 &devmode.driverversion,
2609 &devmode.driverextra,
2610 &devmode.orientation,
2612 &devmode.paperlength,
2613 &devmode.paperwidth,
2616 &devmode.defaultsource,
2617 &devmode.printquality,
2620 &devmode.yresolution,
2626 &devmode.bitsperpel,
2628 &devmode.pelsheight,
2629 &devmode.displayflags,
2630 &devmode.displayfrequency,
2634 &devmode.dithertype,
2637 &devmode.panningwidth,
2638 &devmode.panningheight,
2639 &devmode.nt_dev_private);
2641 if (devmode.nt_dev_private) {
2642 /* the len in tdb_unpack is an int value and
2643 * devmode.driverextra is only a short
2645 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2646 devmode.driverextra=(uint16)extra_len;
2648 /* check to catch an invalid TDB entry so we don't segfault */
2649 if (devmode.driverextra == 0) {
2650 devmode.nt_dev_private = NULL;
2654 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2656 SAFE_FREE(devmode.nt_dev_private);
2660 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2661 if (devmode.nt_dev_private)
2662 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2667 /****************************************************************************
2668 Allocate and initialize a new slot.
2669 ***************************************************************************/
2671 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2676 if ( !name || !data )
2679 /* allocate another slot in the NT_PRINTER_KEY array */
2681 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2682 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2688 key_index = data->num_keys;
2690 /* initialze new key */
2692 data->keys[key_index].name = talloc_strdup( data, name );
2694 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2699 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2704 /****************************************************************************
2705 search for a registry key name in the existing printer data
2706 ***************************************************************************/
2708 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2712 for ( i=0; i<data->num_keys; i++ ) {
2713 if ( strequal( data->keys[i].name, name ) ) {
2715 /* cleanup memory */
2717 TALLOC_FREE( data->keys[i].name );
2718 TALLOC_FREE( data->keys[i].values );
2720 /* if not the end of the array, move remaining elements down one slot */
2723 if ( data->num_keys && (i < data->num_keys) )
2724 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2731 return data->num_keys;
2734 /****************************************************************************
2735 search for a registry key name in the existing printer data
2736 ***************************************************************************/
2738 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2743 if ( !data || !name )
2746 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2748 /* loop over all existing keys */
2750 for ( i=0; i<data->num_keys; i++ ) {
2751 if ( strequal(data->keys[i].name, name) ) {
2752 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2762 /****************************************************************************
2763 ***************************************************************************/
2765 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2769 int num_subkeys = 0;
2771 fstring *subkeys_ptr = NULL;
2782 /* special case of asking for the top level printer data registry key names */
2784 if ( strlen(key) == 0 ) {
2785 for ( i=0; i<data->num_keys; i++ ) {
2787 /* found a match, so allocate space and copy the name */
2789 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2790 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2795 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2802 /* asking for the subkeys of some key */
2803 /* subkey paths are stored in the key name using '\' as the delimiter */
2805 for ( i=0; i<data->num_keys; i++ ) {
2806 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2808 /* if we found the exact key, then break */
2809 key_len = strlen( key );
2810 if ( strlen(data->keys[i].name) == key_len )
2813 /* get subkey path */
2815 p = data->keys[i].name + key_len;
2818 fstrcpy( subkeyname, p );
2819 if ( (p = strchr( subkeyname, '\\' )) )
2822 /* don't add a key more than once */
2824 for ( j=0; j<num_subkeys; j++ ) {
2825 if ( strequal( subkeys_ptr[j], subkeyname ) )
2829 if ( j != num_subkeys )
2832 /* found a match, so allocate space and copy the name */
2834 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2835 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2840 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2846 /* return error if the key was not found */
2848 if ( i == data->num_keys ) {
2849 SAFE_FREE(subkeys_ptr);
2854 /* tag off the end */
2857 fstrcpy(subkeys_ptr[num_subkeys], "" );
2859 *subkeys = subkeys_ptr;
2865 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2868 smb_ucs2_t conv_str[1024];
2871 regval_ctr_delvalue(ctr, val_name);
2872 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2873 STR_TERMINATE | STR_NOALIGN);
2874 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2875 (char *) conv_str, str_size);
2878 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2881 regval_ctr_delvalue(ctr, val_name);
2882 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2883 (char *) &dword, sizeof(dword));
2886 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2889 uint8 bin_bool = (b ? 1 : 0);
2890 regval_ctr_delvalue(ctr, val_name);
2891 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2892 (char *) &bin_bool, sizeof(bin_bool));
2895 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2896 const char *multi_sz)
2898 smb_ucs2_t *conv_strs = NULL;
2901 /* a multi-sz has to have a null string terminator, i.e., the last
2902 string must be followed by two nulls */
2903 str_size = strlen(multi_sz) + 2;
2904 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2909 /* Change to byte units. */
2910 str_size *= sizeof(smb_ucs2_t);
2911 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2912 STR_TERMINATE | STR_NOALIGN);
2914 regval_ctr_delvalue(ctr, val_name);
2915 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2916 (char *) conv_strs, str_size);
2917 safe_free(conv_strs);
2921 /****************************************************************************
2922 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2924 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2925 * @return BOOL indicating success or failure
2926 ***************************************************************************/
2928 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2930 REGVAL_CTR *ctr = NULL;
2933 char *allocated_string = NULL;
2934 const char *ascii_str;
2937 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2938 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2939 ctr = info2->data->keys[i].values;
2941 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2942 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2944 /* we make the assumption that the netbios name is the same
2945 as the DNS name sinc ethe former will be what we used to
2948 if ( get_mydnsdomname( dnssuffix ) )
2949 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2951 fstrcpy( longname, global_myname() );
2953 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2955 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2956 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2957 SAFE_FREE(allocated_string);
2959 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2960 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2961 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2962 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2963 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2964 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2965 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2966 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2967 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2969 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2970 (info2->attributes &
2971 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2973 switch (info2->attributes & 0x3) {
2975 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2978 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2981 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2984 ascii_str = "unknown";
2986 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2991 /*****************************************************************
2992 ****************************************************************/
2994 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2998 REGVAL_CTR *ctr=NULL;
2999 UNISTR2 unistr_guid;
3001 /* find the DsSpooler key */
3002 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3003 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3004 ctr = info2->data->keys[i].values;
3006 regval_ctr_delvalue(ctr, "objectGUID");
3008 /* We used to store this as a REG_BINARY but that causes
3011 ZERO_STRUCT( unistr_guid );
3012 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3013 UNI_STR_TERMINATE );
3015 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3016 (char *)unistr_guid.buffer,
3017 unistr_guid.uni_max_len*2);
3021 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3022 NT_PRINTER_INFO_LEVEL *printer)
3026 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3027 char *srv_dn_utf8, **srv_cn_utf8;
3030 const char *attrs[] = {"objectGUID", NULL};
3032 WERROR win_rc = WERR_OK;
3034 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3036 /* figure out where to publish */
3037 ads_find_machine_acct(ads, &res, global_myname());
3039 /* We use ldap_get_dn here as we need the answer
3040 * in utf8 to call ldap_explode_dn(). JRA. */
3042 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
3045 return WERR_SERVER_UNAVAILABLE;
3047 ads_msgfree(ads, res);
3048 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3050 ldap_memfree(srv_dn_utf8);
3052 return WERR_SERVER_UNAVAILABLE;
3054 /* Now convert to CH_UNIX. */
3055 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3056 ldap_memfree(srv_dn_utf8);
3057 ldap_memfree(srv_cn_utf8);
3059 return WERR_SERVER_UNAVAILABLE;
3061 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3062 ldap_memfree(srv_dn_utf8);
3063 ldap_memfree(srv_cn_utf8);
3066 return WERR_SERVER_UNAVAILABLE;
3069 ldap_memfree(srv_dn_utf8);
3070 ldap_memfree(srv_cn_utf8);
3072 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3073 if (!srv_cn_escaped) {
3074 SAFE_FREE(srv_cn_0);
3075 ldap_memfree(srv_dn_utf8);
3077 return WERR_SERVER_UNAVAILABLE;
3079 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3080 if (!sharename_escaped) {
3081 SAFE_FREE(srv_cn_escaped);
3082 SAFE_FREE(srv_cn_0);
3083 ldap_memfree(srv_dn_utf8);
3085 return WERR_SERVER_UNAVAILABLE;
3089 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3092 SAFE_FREE(srv_cn_0);
3093 SAFE_FREE(srv_cn_escaped);
3094 SAFE_FREE(sharename_escaped);
3096 /* build the ads mods */
3097 ctx = talloc_init("nt_printer_publish_ads");
3103 mods = ads_init_mods(ctx);
3107 talloc_destroy(ctx);
3111 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3112 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3113 printer->info_2->sharename);
3116 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3117 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3118 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3120 if (!ADS_ERR_OK(ads_rc))
3121 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3123 talloc_destroy(ctx);
3125 /* retreive the guid and store it locally */
3126 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3128 ads_pull_guid(ads, res, &guid);
3129 ads_msgfree(ads, res);
3130 store_printer_guid(printer->info_2, guid);
3131 win_rc = mod_a_printer(printer, 2);
3138 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3139 NT_PRINTER_INFO_LEVEL *printer)
3143 char *prt_dn = NULL;
3145 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3147 /* remove the printer from the directory */
3148 ads_rc = ads_find_printer_on_server(ads, &res,
3149 printer->info_2->sharename, global_myname());
3151 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3152 prt_dn = ads_get_dn(ads, res);
3154 ads_msgfree(ads, res);
3157 ads_rc = ads_del_dn(ads, prt_dn);
3158 ads_memfree(ads, prt_dn);
3161 ads_msgfree(ads, res);
3165 /****************************************************************************
3166 * Publish a printer in the directory
3168 * @param snum describing printer service
3169 * @return WERROR indicating status of publishing
3170 ***************************************************************************/
3172 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3175 ADS_STRUCT *ads = NULL;
3176 NT_PRINTER_INFO_LEVEL *printer = NULL;
3179 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3180 if (!W_ERROR_IS_OK(win_rc))
3184 case SPOOL_DS_PUBLISH:
3185 case SPOOL_DS_UPDATE:
3186 /* set the DsSpooler info and attributes */
3187 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3188 win_rc = WERR_NOMEM;
3192 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3194 case SPOOL_DS_UNPUBLISH:
3195 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3198 win_rc = WERR_NOT_SUPPORTED;
3202 win_rc = mod_a_printer(printer, 2);
3203 if (!W_ERROR_IS_OK(win_rc)) {
3204 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3208 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3210 DEBUG(3, ("ads_init() failed\n"));
3211 win_rc = WERR_SERVER_UNAVAILABLE;
3214 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3215 SAFE_FREE(ads->auth.password);
3216 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3219 /* ads_connect() will find the DC for us */
3220 ads_rc = ads_connect(ads);
3221 if (!ADS_ERR_OK(ads_rc)) {
3222 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3223 win_rc = WERR_ACCESS_DENIED;
3228 case SPOOL_DS_PUBLISH:
3229 case SPOOL_DS_UPDATE:
3230 win_rc = nt_printer_publish_ads(ads, printer);
3232 case SPOOL_DS_UNPUBLISH:
3233 win_rc = nt_printer_unpublish_ads(ads, printer);
3238 free_a_printer(&printer, 2);
3243 WERROR check_published_printers(void)
3246 ADS_STRUCT *ads = NULL;
3248 int n_services = lp_numservices();
3249 NT_PRINTER_INFO_LEVEL *printer = NULL;
3251 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3253 DEBUG(3, ("ads_init() failed\n"));
3254 return WERR_SERVER_UNAVAILABLE;
3256 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3257 SAFE_FREE(ads->auth.password);
3258 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3261 /* ads_connect() will find the DC for us */
3262 ads_rc = ads_connect(ads);
3263 if (!ADS_ERR_OK(ads_rc)) {
3264 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3266 return WERR_ACCESS_DENIED;
3269 for (snum = 0; snum < n_services; snum++) {
3270 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3273 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3274 lp_servicename(snum))) &&
3275 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3276 nt_printer_publish_ads(ads, printer);
3278 free_a_printer(&printer, 2);
3285 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3288 NT_PRINTER_INFO_LEVEL *printer = NULL;
3290 REGISTRY_VALUE *guid_val;
3295 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3297 if (!W_ERROR_IS_OK(win_rc) ||
3298 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3299 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3300 !(ctr = printer->info_2->data->keys[i].values) ||
3301 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3303 free_a_printer(&printer, 2);
3307 /* fetching printer guids really ought to be a separate function. */
3312 /* We used to store the guid as REG_BINARY, then swapped
3313 to REG_SZ for Vista compatibility so check for both */
3315 switch ( regval_type(guid_val) ){
3317 rpcstr_pull( guid_str, regval_data_p(guid_val),
3318 sizeof(guid_str)-1, -1, STR_TERMINATE );
3319 ret = smb_string_to_uuid( guid_str, guid );
3322 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3326 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3329 DEBUG(0,("is_printer_published: GUID value stored as "
3330 "invaluid type (%d)\n", regval_type(guid_val) ));
3335 free_a_printer(&printer, 2);
3339 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3344 WERROR check_published_printers(void)
3349 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3354 #endif /* HAVE_ADS */
3356 /****************************************************************************
3357 ***************************************************************************/
3359 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3361 NT_PRINTER_DATA *data;
3363 int removed_keys = 0;
3367 empty_slot = data->num_keys;
3370 return WERR_INVALID_PARAM;
3372 /* remove all keys */
3374 if ( !strlen(key) ) {
3376 TALLOC_FREE( data );
3380 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3386 /* remove a specific key (and all subkeys) */
3388 for ( i=0; i<data->num_keys; i++ ) {
3389 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3390 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3391 data->keys[i].name));
3393 TALLOC_FREE( data->keys[i].name );
3394 TALLOC_FREE( data->keys[i].values );
3396 /* mark the slot as empty */
3398 ZERO_STRUCTP( &data->keys[i] );
3402 /* find the first empty slot */
3404 for ( i=0; i<data->num_keys; i++ ) {
3405 if ( !data->keys[i].name ) {
3412 if ( i == data->num_keys )
3413 /* nothing was removed */
3414 return WERR_INVALID_PARAM;
3416 /* move everything down */
3418 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3419 if ( data->keys[i].name ) {
3420 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3421 ZERO_STRUCTP( &data->keys[i] );
3429 data->num_keys -= removed_keys;
3431 /* sanity check to see if anything is left */
3433 if ( !data->num_keys ) {
3434 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3436 SAFE_FREE( data->keys );
3437 ZERO_STRUCTP( data );
3443 /****************************************************************************
3444 ***************************************************************************/
3446 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3448 WERROR result = WERR_OK;
3451 /* we must have names on non-zero length */
3453 if ( !key || !*key|| !value || !*value )
3454 return WERR_INVALID_NAME;
3456 /* find the printer key first */
3458 key_index = lookup_printerkey( p2->data, key );
3459 if ( key_index == -1 )
3462 /* make sure the value exists so we can return the correct error code */
3464 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3465 return WERR_BADFILE;
3467 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3469 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3475 /****************************************************************************
3476 ***************************************************************************/
3478 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3479 uint32 type, uint8 *data, int real_len )
3481 WERROR result = WERR_OK;
3484 /* we must have names on non-zero length */
3486 if ( !key || !*key|| !value || !*value )
3487 return WERR_INVALID_NAME;
3489 /* find the printer key first */
3491 key_index = lookup_printerkey( p2->data, key );
3492 if ( key_index == -1 )
3493 key_index = add_new_printer_key( p2->data, key );
3495 if ( key_index == -1 )
3498 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3499 type, (const char *)data, real_len );
3501 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3502 key, value, type, real_len ));
3507 /****************************************************************************
3508 ***************************************************************************/
3510 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3514 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3517 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3520 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3523 /****************************************************************************
3524 Unpack a list of registry values frem the TDB
3525 ***************************************************************************/
3527 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3531 pstring string, valuename, keyname;
3535 REGISTRY_VALUE *regval_p;
3538 /* add the "PrinterDriverData" key first for performance reasons */
3540 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3542 /* loop and unpack the rest of the registry values */
3546 /* check to see if there are any more registry values */
3549 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3553 /* unpack the next regval */
3555 len += tdb_unpack(buf+len, buflen-len, "fdB",
3561 /* lookup for subkey names which have a type of REG_NONE */
3562 /* there's no data with this entry */
3564 if ( type == REG_NONE ) {
3565 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3566 add_new_printer_key( printer_data, string );
3571 * break of the keyname from the value name.
3572 * Valuenames can have embedded '\'s so be careful.
3573 * only support one level of keys. See the
3574 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3578 str = strchr_m( string, '\\');
3580 /* Put in "PrinterDriverData" is no key specified */
3583 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3584 pstrcpy( valuename, string );
3588 pstrcpy( keyname, string );
3589 pstrcpy( valuename, str+1 );
3592 /* see if we need a new key */
3594 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3595 key_index = add_new_printer_key( printer_data, keyname );
3597 if ( key_index == -1 ) {
3598 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3603 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3605 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3606 Thanks to Martin Zielinski for the hint. */
3608 if ( type == REG_BINARY &&
3609 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3610 strequal( valuename, "objectGUID" ) )
3613 UNISTR2 unistr_guid;
3615 ZERO_STRUCT( unistr_guid );
3617 /* convert the GUID to a UNICODE string */
3619 memcpy( &guid, data_p, sizeof(struct GUID) );
3621 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3622 UNI_STR_TERMINATE );
3624 regval_ctr_addvalue( printer_data->keys[key_index].values,
3626 (const char *)unistr_guid.buffer,
3627 unistr_guid.uni_str_len*2 );
3632 regval_ctr_addvalue( printer_data->keys[key_index].values,
3633 valuename, type, (const char *)data_p,
3638 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3645 /****************************************************************************
3646 ***************************************************************************/
3648 static void map_to_os2_driver(fstring drivername)
3650 static BOOL initialised=False;
3651 static fstring last_from,last_to;
3652 char *mapfile = lp_os2_driver_map();
3653 char **lines = NULL;
3657 if (!strlen(drivername))
3664 *last_from = *last_to = 0;
3668 if (strequal(drivername,last_from)) {
3669 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3670 fstrcpy(drivername,last_to);
3674 lines = file_lines_load(mapfile, &numlines,0);
3675 if (numlines == 0 || lines == NULL) {
3676 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3681 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3683 for( i = 0; i < numlines; i++) {
3684 char *nt_name = lines[i];
3685 char *os2_name = strchr(nt_name,'=');
3692 while (isspace(*nt_name))
3695 if (!*nt_name || strchr("#;",*nt_name))
3699 int l = strlen(nt_name);
3700 while (l && isspace(nt_name[l-1])) {
3706 while (isspace(*os2_name))
3710 int l = strlen(os2_name);
3711 while (l && isspace(os2_name[l-1])) {
3717 if (strequal(nt_name,drivername)) {
3718 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3719 fstrcpy(last_from,drivername);
3720 fstrcpy(last_to,os2_name);
3721 fstrcpy(drivername,os2_name);
3722 file_lines_free(lines);
3727 file_lines_free(lines);
3730 /****************************************************************************
3731 Get a default printer info 2 struct.
3732 ****************************************************************************/
3733 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3735 int snum = lp_servicenumber(sharename);
3737 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3738 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3739 servername, sharename);
3740 fstrcpy(info->sharename, sharename);
3741 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3743 /* by setting the driver name to an empty string, a local NT admin
3744 can now run the **local** APW to install a local printer driver
3745 for a Samba shared printer in 2.2. Without this, drivers **must** be
3746 installed on the Samba server for NT clients --jerry */
3747 #if 0 /* JERRY --do not uncomment-- */
3748 if (!*info->drivername)
3749 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3753 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3755 pstrcpy(info->comment, "");
3756 fstrcpy(info->printprocessor, "winprint");
3757 fstrcpy(info->datatype, "RAW");
3760 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3761 /* Pull the location and comment strings from cups if we don't
3763 if ( !strlen(info->location) || !strlen(info->comment) )
3764 cups_pull_comment_location( info );
3768 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3770 info->starttime = 0; /* Minutes since 12:00am GMT */
3771 info->untiltime = 0; /* Minutes since 12:00am GMT */
3773 info->default_priority = 1;
3774 info->setuptime = (uint32)time(NULL);
3777 * I changed this as I think it is better to have a generic
3778 * DEVMODE than to crash Win2k explorer.exe --jerry
3779 * See the HP Deskjet 990c Win2k drivers for an example.
3781 * However the default devmode appears to cause problems
3782 * with the HP CLJ 8500 PCL driver. Hence the addition of
3783 * the "default devmode" parameter --jerry 22/01/2002
3786 if (lp_default_devmode(snum)) {
3787 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3791 info->devmode = NULL;
3794 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3802 free_nt_devicemode(&info->devmode);
3804 return WERR_ACCESS_DENIED;
3807 /****************************************************************************
3808 ****************************************************************************/
3809 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3812 int snum = lp_servicenumber(sharename);
3813 TDB_DATA kbuf, dbuf;
3814 fstring printername;
3815 char adevice[MAXDEVICENAME];
3817 kbuf = make_printer_tdbkey( sharename );
3819 dbuf = tdb_fetch(tdb_printers, kbuf);
3821 return get_a_printer_2_default(info, servername, sharename);
3824 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3827 &info->default_priority,
3834 &info->c_setprinter,
3844 info->printprocessor,
3848 /* Samba has to have shared raw drivers. */
3849 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3850 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3852 /* Restore the stripped strings. */
3853 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3855 if ( lp_force_printername(snum) ) {
3856 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3858 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3861 fstrcpy(info->printername, printername);
3864 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3865 /* Pull the location and comment strings from cups if we don't
3867 if ( !strlen(info->location) || !strlen(info->comment) )
3868 cups_pull_comment_location( info );
3872 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3875 * Some client drivers freak out if there is a NULL devmode
3876 * (probably the driver is not checking before accessing
3877 * the devmode pointer) --jerry
3879 * See comments in get_a_printer_2_default()
3882 if (lp_default_devmode(snum) && !info->devmode) {
3883 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3885 info->devmode = construct_nt_devicemode(printername);
3888 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3889 if (info->devmode) {
3890 fstrcpy(info->devmode->devicename, adevice);
3893 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3894 DEBUG(0,("unpack_values: talloc() failed!\n"));
3895 SAFE_FREE(dbuf.dptr);
3898 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3900 /* This will get the current RPC talloc context, but we should be
3901 passing this as a parameter... fixme... JRA ! */
3903 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3904 SAFE_FREE(dbuf.dptr);
3908 /* Fix for OS/2 drivers. */
3910 if (get_remote_arch() == RA_OS2) {
3911 map_to_os2_driver(info->drivername);
3914 SAFE_FREE(dbuf.dptr);
3916 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3917 sharename, info->printername, info->drivername));
3922 /****************************************************************************
3923 Debugging function, dump at level 6 the struct in the logs.
3924 ****************************************************************************/
3925 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3928 NT_PRINTER_INFO_LEVEL_2 *info2;
3930 DEBUG(106,("Dumping printer at level [%d]\n", level));
3935 if (printer->info_2 == NULL)
3939 info2=printer->info_2;
3941 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3942 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3943 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3944 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3945 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3946 DEBUGADD(106,("status:[%d]\n", info2->status));
3947 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3948 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3949 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3950 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3951 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3953 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3954 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3955 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3956 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3957 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3958 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3959 DEBUGADD(106,("location:[%s]\n", info2->location));
3960 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3961 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3962 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3963 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3969 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3977 /****************************************************************************
3978 Update the changeid time.
3979 This is SO NASTY as some drivers need this to change, others need it
3980 static. This value will change every second, and I must hope that this
3981 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3983 ****************************************************************************/
3985 static uint32 rev_changeid(void)
3989 get_process_uptime(&tv);
3992 /* Return changeid as msec since spooler restart */
3993 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3996 * This setting seems to work well but is too untested
3997 * to replace the above calculation. Left in for experiementation
3998 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4000 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4006 * The function below are the high level ones.
4007 * only those ones must be called from the spoolss code.
4011 /****************************************************************************
4012 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4013 ****************************************************************************/
4015 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4019 dump_a_printer(printer, level);
4025 * Update the changestamp. Emperical tests show that the
4026 * ChangeID is always updated,but c_setprinter is
4027 * global spooler variable (not per printer).
4030 /* ChangeID **must** be increasing over the lifetime
4031 of client's spoolss service in order for the
4032 client's cache to show updates */
4034 printer->info_2->changeid = rev_changeid();
4037 * Because one day someone will ask:
4038 * NT->NT An admin connection to a remote
4039 * printer show changes imeediately in
4040 * the properities dialog
4042 * A non-admin connection will only show the
4043 * changes after viewing the properites page
4044 * 2 times. Seems to be related to a
4045 * race condition in the client between the spooler
4046 * updating the local cache and the Explorer.exe GUI
4047 * actually displaying the properties.
4049 * This is fixed in Win2k. admin/non-admin
4050 * connections both display changes immediately.
4055 result=update_a_printer_2(printer->info_2);
4060 result=WERR_UNKNOWN_LEVEL;
4067 /****************************************************************************
4068 Initialize printer devmode & data with previously saved driver init values.
4069 ****************************************************************************/
4071 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4076 NT_PRINTER_INFO_LEVEL_2 info;
4082 * Delete any printer data 'values' already set. When called for driver
4083 * replace, there will generally be some, but during an add printer, there
4084 * should not be any (if there are delete them).
4087 if ( info_ptr->data )
4088 delete_all_printer_data( info_ptr, "" );
4090 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4092 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4095 * When changing to a driver that has no init info in the tdb, remove
4096 * the previous drivers init info and leave the new on blank.
4098 free_nt_devicemode(&info_ptr->devmode);
4103 * Get the saved DEVMODE..
4106 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4109 * The saved DEVMODE contains the devicename from the printer used during
4110 * the initialization save. Change it to reflect the new printer.
4113 if ( info.devmode ) {
4114 ZERO_STRUCT(info.devmode->devicename);
4115 fstrcpy(info.devmode->devicename, info_ptr->printername);
4119 * NT/2k does not change out the entire DeviceMode of a printer
4120 * when changing the driver. Only the driverextra, private, &
4121 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4123 * Later examination revealed that Windows NT/2k does reset the
4124 * the printer's device mode, bit **only** when you change a
4125 * property of the device mode such as the page orientation.
4130 /* Bind the saved DEVMODE to the new the printer */
4132 free_nt_devicemode(&info_ptr->devmode);
4133 info_ptr->devmode = info.devmode;
4135 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4136 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4138 /* Add the printer data 'values' to the new printer */
4140 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4141 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4145 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4148 SAFE_FREE(dbuf.dptr);
4153 /****************************************************************************
4154 Initialize printer devmode & data with previously saved driver init values.
4155 When a printer is created using AddPrinter, the drivername bound to the
4156 printer is used to lookup previously saved driver initialization info, which
4157 is bound to the new printer.
4158 ****************************************************************************/
4160 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4162 BOOL result = False;
4166 result = set_driver_init_2(printer->info_2);
4170 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4178 /****************************************************************************
4179 Delete driver init data stored for a specified driver
4180 ****************************************************************************/
4182 BOOL del_driver_init(char *drivername)
4186 if (!drivername || !*drivername) {
4187 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4191 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4193 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4195 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4198 /****************************************************************************
4199 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4200 in the tdb. Note: this is different from the driver entry and the printer
4201 entry. There should be a single driver init entry for each driver regardless
4202 of whether it was installed from NT or 2K. Technically, they should be
4203 different, but they work out to the same struct.
4204 ****************************************************************************/
4206 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4210 int buflen, len, ret;
4218 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4220 len += pack_values( info->data, buf+len, buflen-len );
4223 buf = (char *)SMB_REALLOC(buf, len);
4225 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4233 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4238 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4242 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4246 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4247 info->sharename, info->drivername));
4252 /****************************************************************************
4253 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4254 ****************************************************************************/
4256 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4260 dump_a_printer(printer, level);
4264 result = update_driver_init_2(printer->info_2);
4274 /****************************************************************************
4275 Convert the printer data value, a REG_BINARY array, into an initialization
4276 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4277 got to keep the endians happy :).
4278 ****************************************************************************/
4280 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4282 BOOL result = False;
4286 ZERO_STRUCT(devmode);
4288 prs_init(&ps, 0, ctx, UNMARSHALL);
4289 ps.data_p = (char *)data;
4290 ps.buffer_size = data_len;
4292 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4293 result = convert_devicemode("", &devmode, &nt_devmode);
4295 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4300 /****************************************************************************
4301 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4303 1. Use the driver's config DLL to this UNC printername and:
4304 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4305 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4306 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4308 The last step triggers saving the "driver initialization" information for
4309 this printer into the tdb. Later, new printers that use this driver will
4310 have this initialization information bound to them. This simulates the
4311 driver initialization, as if it had run on the Samba server (as it would
4314 The Win32 client side code requirement sucks! But until we can run arbitrary
4315 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4317 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4318 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4319 about it and you will realize why. JRR 010720
4320 ****************************************************************************/
4322 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4324 WERROR status = WERR_OK;
4325 TALLOC_CTX *ctx = NULL;
4326 NT_DEVICEMODE *nt_devmode = NULL;
4327 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4330 * When the DEVMODE is already set on the printer, don't try to unpack it.
4332 DEBUG(8,("save_driver_init_2: Enter...\n"));
4334 if ( !printer->info_2->devmode && data_len ) {
4336 * Set devmode on printer info, so entire printer initialization can be
4340 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4343 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4344 status = WERR_NOMEM;
4348 ZERO_STRUCTP(nt_devmode);
4351 * The DEVMODE is held in the 'data' component of the param in raw binary.
4352 * Convert it to to a devmode structure
4354 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4355 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4356 status = WERR_INVALID_PARAM;
4360 printer->info_2->devmode = nt_devmode;
4364 * Pack up and add (or update) the DEVMODE and any current printer data to
4365 * a 'driver init' element in the tdb
4369 if ( update_driver_init(printer, 2) != 0 ) {
4370 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4371 status = WERR_NOMEM;
4376 * If driver initialization info was successfully saved, set the current
4377 * printer to match it. This allows initialization of the current printer
4378 * as well as the driver.
4380 status = mod_a_printer(printer, 2);
4381 if (!W_ERROR_IS_OK(status)) {
4382 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4383 printer->info_2->printername));
4387 talloc_destroy(ctx);
4388 free_nt_devicemode( &nt_devmode );
4390 printer->info_2->devmode = tmp_devmode;
4395 /****************************************************************************
4396 Update the driver init info (DEVMODE and specifics) for a printer
4397 ****************************************************************************/
4399 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4401 WERROR status = WERR_OK;
4405 status = save_driver_init_2( printer, data, data_len );
4408 status = WERR_UNKNOWN_LEVEL;
4415 /****************************************************************************
4416 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4418 Previously the code had a memory allocation problem because it always
4419 used the TALLOC_CTX from the Printer_entry*. This context lasts
4420 as a long as the original handle is open. So if the client made a lot
4421 of getprinter[data]() calls, the memory usage would climb. Now we use
4422 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4423 still use the Printer_entry->ctx for maintaining the cache copy though
4424 since that object must live as long as the handle by definition.
4427 ****************************************************************************/
4429 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4430 const char *sharename)
4435 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4437 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4438 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4444 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4445 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4446 TALLOC_FREE( *pp_printer );
4451 fstrcpy( servername, print_hnd->servername );
4453 fstrcpy( servername, "%L" );
4454 standard_sub_basic( "", "", servername,
4455 sizeof(servername)-1 );
4458 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4461 /* we have a new printer now. Save it with this handle */
4463 if ( !W_ERROR_IS_OK(result) ) {
4464 TALLOC_FREE( *pp_printer );
4465 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4466 sharename, (unsigned int)level, dos_errstr(result)));
4470 dump_a_printer( *pp_printer, level);
4475 TALLOC_FREE( *pp_printer );
4476 return WERR_UNKNOWN_LEVEL;
4482 /****************************************************************************
4483 Deletes a NT_PRINTER_INFO_LEVEL struct.
4484 ****************************************************************************/
4486 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4488 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4495 if ( printer->info_2 )
4496 free_nt_printer_info_level_2(&printer->info_2);
4500 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4504 TALLOC_FREE(*pp_printer);
4509 /****************************************************************************
4510 ****************************************************************************/
4511 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4514 DEBUG(104,("adding a printer at level [%d]\n", level));
4515 dump_a_printer_driver(driver, level);
4519 result=add_a_printer_driver_3(driver.info_3);
4523 result=add_a_printer_driver_6(driver.info_6);
4533 /****************************************************************************
4534 ****************************************************************************/
4536 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4537 fstring drivername, const char *architecture, uint32 version)
4543 /* Sometime we just want any version of the driver */
4545 if ( version == DRIVER_ANY_VERSION ) {
4546 /* look for Win2k first and then for NT4 */
4547 result = get_a_printer_driver_3(&driver->info_3, drivername,
4550 if ( !W_ERROR_IS_OK(result) ) {
4551 result = get_a_printer_driver_3( &driver->info_3,
4552 drivername, architecture, 2 );
4555 result = get_a_printer_driver_3(&driver->info_3, drivername,
4556 architecture, version);
4565 if (W_ERROR_IS_OK(result))
4566 dump_a_printer_driver(*driver, level);
4571 /****************************************************************************
4572 ****************************************************************************/
4573 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4580 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4581 if (driver.info_3 != NULL)
4583 info3=driver.info_3;
4584 SAFE_FREE(info3->dependentfiles);
4585 ZERO_STRUCTP(info3);
4595 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4596 if (driver.info_6 != NULL) {
4597 info6=driver.info_6;
4598 SAFE_FREE(info6->dependentfiles);
4599 SAFE_FREE(info6->previousnames);
4600 ZERO_STRUCTP(info6);
4616 /****************************************************************************
4617 Determine whether or not a particular driver is currently assigned
4619 ****************************************************************************/
4621 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4624 int n_services = lp_numservices();
4625 NT_PRINTER_INFO_LEVEL *printer = NULL;
4626 BOOL in_use = False;
4631 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4633 /* loop through the printers.tdb and check for the drivername */
4635 for (snum=0; snum<n_services && !in_use; snum++) {
4636 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4639 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4642 if ( strequal(info_3->name, printer->info_2->drivername) )
4645 free_a_printer( &printer, 2 );
4648 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4651 NT_PRINTER_DRIVER_INFO_LEVEL d;
4654 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4656 /* we can still remove the driver if there is one of
4657 "Windows NT x86" version 2 or 3 left */
4659 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4660 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4663 switch ( info_3->cversion ) {
4665 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4668 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4671 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4673 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4678 /* now check the error code */
4680 if ( W_ERROR_IS_OK(werr) ) {
4681 /* it's ok to remove the driver, we have other architctures left */
4683 free_a_printer_driver( d, 3 );
4687 /* report that the driver is not in use by default */
4693 /**********************************************************************
4694 Check to see if a ogiven file is in use by *info
4695 *********************************************************************/
4697 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4704 if ( strequal(file, info->driverpath) )
4707 if ( strequal(file, info->datafile) )
4710 if ( strequal(file, info->configfile) )
4713 if ( strequal(file, info->helpfile) )
4716 /* see of there are any dependent files to examine */
4718 if ( !info->dependentfiles )
4721 while ( *info->dependentfiles[i] ) {
4722 if ( strequal(file, info->dependentfiles[i]) )
4731 /**********************************************************************
4732 Utility function to remove the dependent file pointed to by the
4733 input parameter from the list
4734 *********************************************************************/
4736 static void trim_dependent_file( fstring files[], int idx )
4739 /* bump everything down a slot */
4741 while( *files[idx+1] ) {
4742 fstrcpy( files[idx], files[idx+1] );
4751 /**********************************************************************
4752 Check if any of the files used by src are also used by drv
4753 *********************************************************************/
4755 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4756 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4758 BOOL in_use = False;
4764 /* check each file. Remove it from the src structure if it overlaps */
4766 if ( drv_file_in_use(src->driverpath, drv) ) {
4768 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4769 fstrcpy( src->driverpath, "" );
4772 if ( drv_file_in_use(src->datafile, drv) ) {
4774 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4775 fstrcpy( src->datafile, "" );
4778 if ( drv_file_in_use(src->configfile, drv) ) {
4780 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4781 fstrcpy( src->configfile, "" );
4784 if ( drv_file_in_use(src->helpfile, drv) ) {
4786 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4787 fstrcpy( src->helpfile, "" );
4790 /* are there any dependentfiles to examine? */
4792 if ( !src->dependentfiles )
4795 while ( *src->dependentfiles[i] ) {
4796 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4798 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4799 trim_dependent_file( src->dependentfiles, i );
4807 /****************************************************************************
4808 Determine whether or not a particular driver files are currently being
4809 used by any other driver.
4811 Return value is True if any files were in use by other drivers
4812 and False otherwise.
4814 Upon return, *info has been modified to only contain the driver files
4815 which are not in use
4816 ****************************************************************************/
4818 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4823 fstring *list = NULL;
4824 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4829 version = info->cversion;
4831 /* loop over all driver versions */
4833 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4835 /* get the list of drivers */
4838 ndrivers = get_ntdrivers(&list, info->environment, version);
4840 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4841 ndrivers, info->environment, version));
4843 /* check each driver for overlap in files */
4845 for (i=0; i<ndrivers; i++) {
4846 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4848 ZERO_STRUCT(driver);
4850 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4855 /* check if d2 uses any files from d1 */
4856 /* only if this is a different driver than the one being deleted */
4858 if ( !strequal(info->name, driver.info_3->name) ) {
4859 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4860 free_a_printer_driver(driver, 3);
4866 free_a_printer_driver(driver, 3);
4871 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4873 driver.info_3 = info;
4875 if ( DEBUGLEVEL >= 20 )
4876 dump_a_printer_driver( driver, 3 );
4881 /****************************************************************************
4882 Actually delete the driver files. Make sure that
4883 printer_driver_files_in_use() return False before calling
4885 ****************************************************************************/
4887 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4892 connection_struct *conn;
4901 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4904 * Connect to the print$ share under the same account as the
4905 * user connected to the rpc pipe. Note we must be root to
4909 null_pw = data_blob( NULL, 0 );
4910 fstrcpy(res_type, "A:");
4912 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4916 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4920 if ( !CAN_WRITE(conn) ) {
4921 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4925 /* Save who we are - we are temporarily becoming the connection user. */
4927 if ( !become_user(conn, conn->vuid) ) {
4928 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4932 /* now delete the files; must strip the '\print$' string from
4935 if ( *info_3->driverpath ) {
4936 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4938 driver_unix_convert(file, conn, NULL, &st);
4939 DEBUG(10,("deleting driverfile [%s]\n", s));
4940 unlink_internals(conn, 0, file, False, False);
4944 if ( *info_3->configfile ) {
4945 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4947 driver_unix_convert(file, conn, NULL, &st);
4948 DEBUG(10,("deleting configfile [%s]\n", s));
4949 unlink_internals(conn, 0, file, False, False);
4953 if ( *info_3->datafile ) {
4954 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4956 driver_unix_convert(file, conn, NULL, &st);
4957 DEBUG(10,("deleting datafile [%s]\n", s));
4958 unlink_internals(conn, 0, file, False, False);
4962 if ( *info_3->helpfile ) {
4963 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4965 driver_unix_convert(file, conn, NULL, &st);
4966 DEBUG(10,("deleting helpfile [%s]\n", s));
4967 unlink_internals(conn, 0, file, False, False);
4971 /* check if we are done removing files */
4973 if ( info_3->dependentfiles ) {
4974 while ( info_3->dependentfiles[i][0] ) {
4977 /* bypass the "\print$" portion of the path */
4979 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4981 driver_unix_convert(file, conn, NULL, &st);
4982 DEBUG(10,("deleting dependent file [%s]\n", file));
4983 unlink_internals(conn, 0, file, False, False);
4995 /****************************************************************************
4996 Remove a printer driver from the TDB. This assumes that the the driver was
4997 previously looked up.
4998 ***************************************************************************/
5000 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5001 uint32 version, BOOL delete_files )
5006 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5008 /* delete the tdb data first */
5010 arch = get_short_archi(info_3->environment);
5012 return WERR_UNKNOWN_PRINTER_DRIVER;
5014 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5015 arch, version, info_3->name);
5017 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5018 key, delete_files ? "TRUE" : "FALSE" ));
5020 ctr.info_3 = info_3;
5021 dump_a_printer_driver( ctr, 3 );
5023 /* check if the driver actually exists for this environment */
5025 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5027 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5028 return WERR_UNKNOWN_PRINTER_DRIVER;
5031 SAFE_FREE( dbuf.dptr );
5033 /* ok... the driver exists so the delete should return success */
5035 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5036 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5037 return WERR_ACCESS_DENIED;
5041 * now delete any associated files if delete_files == True
5042 * even if this part failes, we return succes because the
5043 * driver doesn not exist any more
5047 delete_driver_files( info_3, user );
5050 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5055 /****************************************************************************
5056 Store a security desc for a printer.
5057 ****************************************************************************/
5059 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5061 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5062 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5064 TALLOC_CTX *mem_ctx = NULL;
5068 mem_ctx = talloc_init("nt_printing_setsec");
5069 if (mem_ctx == NULL)
5072 /* The old owner and group sids of the security descriptor are not
5073 present when new ACEs are added or removed by changing printer
5074 permissions through NT. If they are NULL in the new security
5075 descriptor then copy them over from the old one. */
5077 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5078 DOM_SID *owner_sid, *group_sid;
5079 SEC_ACL *dacl, *sacl;
5080 SEC_DESC *psd = NULL;
5083 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5084 status = WERR_NOMEM;
5088 /* Pick out correct owner and group sids */
5090 owner_sid = secdesc_ctr->sd->owner_sid ?
5091 secdesc_ctr->sd->owner_sid :
5092 old_secdesc_ctr->sd->owner_sid;
5094 group_sid = secdesc_ctr->sd->group_sid ?
5095 secdesc_ctr->sd->group_sid :
5096 old_secdesc_ctr->sd->group_sid;
5098 dacl = secdesc_ctr->sd->dacl ?
5099 secdesc_ctr->sd->dacl :
5100 old_secdesc_ctr->sd->dacl;
5102 sacl = secdesc_ctr->sd->sacl ?
5103 secdesc_ctr->sd->sacl :
5104 old_secdesc_ctr->sd->sacl;
5106 /* Make a deep copy of the security descriptor */
5108 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5109 owner_sid, group_sid,
5115 status = WERR_NOMEM;
5119 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5122 if (!new_secdesc_ctr) {
5123 new_secdesc_ctr = secdesc_ctr;
5126 /* Store the security descriptor in a tdb */
5128 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5129 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5131 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5133 status = WERR_BADFUNC;
5137 kbuf = make_printers_secdesc_tdbkey( sharename );
5139 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5142 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5143 status = WERR_BADFUNC;
5146 /* Free malloc'ed memory */
5152 talloc_destroy(mem_ctx);
5156 /****************************************************************************
5157 Construct a default security descriptor buffer for a printer.
5158 ****************************************************************************/
5160 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5162 SEC_ACE ace[5]; /* max number of ace entries */
5165 SEC_ACL *psa = NULL;
5166 SEC_DESC_BUF *sdb = NULL;
5167 SEC_DESC *psd = NULL;
5171 /* Create an ACE where Everyone is allowed to print */
5173 init_sec_access(&sa, PRINTER_ACE_PRINT);
5174 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5175 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5177 /* Add the domain admins group if we are a DC */
5180 DOM_SID domadmins_sid;
5182 sid_copy(&domadmins_sid, get_global_sam_sid());
5183 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5185 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5186 init_sec_ace(&ace[i++], &domadmins_sid,
5187 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5188 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5189 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5190 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5192 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5193 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5195 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5196 init_sec_ace(&ace[i++], &adm_sid,
5197 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5198 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5199 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5200 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5203 /* add BUILTIN\Administrators as FULL CONTROL */
5205 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5206 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5207 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5208 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5209 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5210 SEC_ACE_TYPE_ACCESS_ALLOWED,
5211 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5213 /* Make the security descriptor owned by the BUILTIN\Administrators */
5215 /* The ACL revision number in rpc_secdesc.h differs from the one
5216 created by NT when setting ACE entries in printer
5217 descriptors. NT4 complains about the property being edited by a
5220 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5221 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5222 &global_sid_Builtin_Administrators,
5223 &global_sid_Builtin_Administrators,
5224 NULL, psa, &sd_size);
5228 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5232 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5234 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5235 (unsigned int)sd_size));
5240 /****************************************************************************
5241 Get a security desc for a printer.
5242 ****************************************************************************/
5244 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5250 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5251 sharename = temp + 1;
5256 /* Fetch security descriptor from tdb */
5258 kbuf = make_printers_secdesc_tdbkey( sharename );
5260 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5261 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5265 DEBUG(4,("using default secdesc for %s\n", sharename));
5267 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5271 /* Save default security descriptor for later */
5273 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5274 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5276 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5277 tdb_prs_store(tdb_printers, kbuf, &ps);
5287 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5288 this security descriptor has been created when winbindd was
5289 down. Take ownership of security descriptor. */
5291 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5294 /* Change sd owner to workgroup administrator */
5296 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5297 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5298 SEC_DESC *psd = NULL;
5303 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5305 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5307 (*secdesc_ctr)->sd->group_sid,
5308 (*secdesc_ctr)->sd->sacl,
5309 (*secdesc_ctr)->sd->dacl,
5316 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5317 if (!new_secdesc_ctr) {
5321 /* Swap with other one */
5323 *secdesc_ctr = new_secdesc_ctr;
5327 nt_printing_setsec(sharename, *secdesc_ctr);
5331 if (DEBUGLEVEL >= 10) {
5332 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5335 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5336 sharename, the_acl->num_aces));
5338 for (i = 0; i < the_acl->num_aces; i++) {
5341 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5343 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5344 the_acl->aces[i].type, the_acl->aces[i].flags,
5345 the_acl->aces[i].access_mask));
5354 1: level not implemented
5355 2: file doesn't exist
5356 3: can't allocate memory
5357 4: can't free memory
5358 5: non existant struct
5362 A printer and a printer driver are 2 different things.
5363 NT manages them separatelly, Samba does the same.
5364 Why ? Simply because it's easier and it makes sense !
5366 Now explanation: You have 3 printers behind your samba server,
5367 2 of them are the same make and model (laser A and B). But laser B
5368 has an 3000 sheet feeder and laser A doesn't such an option.
5369 Your third printer is an old dot-matrix model for the accounting :-).
5371 If the /usr/local/samba/lib directory (default dir), you will have
5372 5 files to describe all of this.
5374 3 files for the printers (1 by printer):
5377 NTprinter_accounting
5378 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5379 NTdriver_printer model X
5380 NTdriver_printer model Y
5382 jfm: I should use this comment for the text file to explain
5383 same thing for the forms BTW.
5384 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5388 /* Convert generic access rights to printer object specific access rights.
5389 It turns out that NT4 security descriptors use generic access rights and
5390 NT5 the object specific ones. */
5392 void map_printer_permissions(SEC_DESC *sd)
5396 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5397 se_map_generic(&sd->dacl->aces[i].access_mask,
5398 &printer_generic_mapping);
5402 /****************************************************************************
5403 Check a user has permissions to perform the given operation. We use the
5404 permission constants defined in include/rpc_spoolss.h to check the various
5405 actions we perform when checking printer access.
5407 PRINTER_ACCESS_ADMINISTER:
5408 print_queue_pause, print_queue_resume, update_printer_sec,
5409 update_printer, spoolss_addprinterex_level_2,
5410 _spoolss_setprinterdata
5415 JOB_ACCESS_ADMINISTER:
5416 print_job_delete, print_job_pause, print_job_resume,
5419 Try access control in the following order (for performance reasons):
5420 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5421 2) check security descriptor (bit comparisons in memory)
5422 3) "printer admins" (may result in numerous calls to winbind)
5424 ****************************************************************************/
5425 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5427 SEC_DESC_BUF *secdesc = NULL;
5428 uint32 access_granted;
5432 TALLOC_CTX *mem_ctx = NULL;
5433 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5435 /* If user is NULL then use the current_user structure */
5438 user = ¤t_user;
5440 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5442 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5446 /* Get printer name */
5448 pname = PRINTERNAME(snum);
5450 if (!pname || !*pname) {
5455 /* Get printer security descriptor */
5457 if(!(mem_ctx = talloc_init("print_access_check"))) {
5462 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5463 talloc_destroy(mem_ctx);
5468 if (access_type == JOB_ACCESS_ADMINISTER) {
5469 SEC_DESC_BUF *parent_secdesc = secdesc;
5471 /* Create a child security descriptor to check permissions
5472 against. This is because print jobs are child objects
5473 objects of a printer. */
5475 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5478 talloc_destroy(mem_ctx);
5483 /* Now this is the bit that really confuses me. The access
5484 type needs to be changed from JOB_ACCESS_ADMINISTER to
5485 PRINTER_ACCESS_ADMINISTER for this to work. Something
5486 to do with the child (job) object becoming like a
5489 access_type = PRINTER_ACCESS_ADMINISTER;
5494 map_printer_permissions(secdesc->sd);
5496 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5497 &access_granted, &status);
5499 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5501 /* see if we need to try the printer admin list */
5503 if ((access_granted == 0) &&
5504 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5505 user->nt_user_token,
5506 lp_printer_admin(snum)))) {
5507 talloc_destroy(mem_ctx);
5511 talloc_destroy(mem_ctx);
5520 /****************************************************************************
5521 Check the time parameters allow a print operation.
5522 *****************************************************************************/
5524 BOOL print_time_access_check(const char *servicename)
5526 NT_PRINTER_INFO_LEVEL *printer = NULL;
5528 time_t now = time(NULL);
5532 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5535 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5539 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5541 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5544 free_a_printer(&printer, 2);
5552 /****************************************************************************
5553 Fill in the servername sent in the _spoolss_open_printer_ex() call
5554 ****************************************************************************/
5556 char* get_server_name( Printer_entry *printer )
5558 return printer->servername;