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((const char *)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((const char *)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((const char *)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((const char *) 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, (char *)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",
369 (const char *)key.dptr ));
370 tdb_delete( tdb_printers, key );
381 /* is this even valid? */
388 /* update access masks */
390 for ( i=0; i<sec->dacl->num_aces; i++ ) {
391 switch ( sec->dacl->aces[i].access_mask ) {
392 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
393 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
396 case GENERIC_ALL_ACCESS:
397 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
400 case READ_CONTROL_ACCESS:
401 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
403 default: /* no change */
408 /* create a new SEC_DESC with the appropriate owner and group SIDs */
410 string_to_sid(&sid, "S-1-5-32-544" );
411 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
413 NULL, NULL, &size_new_sec );
418 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
424 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
425 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
434 sd_size = sec_desc_size(sd_store->sd) + sizeof(SEC_DESC_BUF);
435 prs_init(&ps, sd_size, ctx, MARSHALL);
437 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
438 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
443 data.dptr = (uint8 *)prs_data_p( &ps );
444 data.dsize = sd_size;
446 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
450 /* 0 to continue and non-zero to stop traversal */
452 return (result == -1);
455 /*******************************************************************
456 *******************************************************************/
458 static BOOL upgrade_to_version_4(void)
463 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
465 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
468 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
470 talloc_destroy( ctx );
472 return ( result != -1 );
475 /*******************************************************************
476 Fix an issue with security descriptors. Printer sec_desc must
477 use more than the generic bits that were previously used
478 in <= 3.0.14a. They must also have a owner and group SID assigned.
479 Otherwise, any printers than have been migrated to a Windows
480 host using printmig.exe will not be accessible.
481 *******************************************************************/
483 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
484 TDB_DATA data, void *state )
488 if (!data.dptr || data.dsize == 0)
491 /* upgrade printer records and security descriptors */
493 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
494 new_key = make_printer_tdbkey( (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
496 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
497 new_key = make_printers_secdesc_tdbkey( (const char *)key.dptr+strlen(SECDESC_PREFIX) );
500 /* ignore this record */
504 /* delete the original record and store under the normalized key */
506 if ( tdb_delete( the_tdb, key ) != 0 ) {
507 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
512 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
513 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
521 /*******************************************************************
522 *******************************************************************/
524 static BOOL upgrade_to_version_5(void)
529 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
531 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
534 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
536 talloc_destroy( ctx );
538 return ( result != -1 );
541 /****************************************************************************
542 Open the NT printing tdbs. Done once before fork().
543 ****************************************************************************/
545 BOOL nt_printing_init(struct messaging_context *msg_ctx)
547 const char *vstring = "INFO/version";
551 if ( tdb_drivers && tdb_printers && tdb_forms )
555 tdb_close(tdb_drivers);
556 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
558 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
559 lock_path("ntdrivers.tdb"), strerror(errno) ));
564 tdb_close(tdb_printers);
565 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
567 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
568 lock_path("ntprinters.tdb"), strerror(errno) ));
573 tdb_close(tdb_forms);
574 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
576 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
577 lock_path("ntforms.tdb"), strerror(errno) ));
581 /* handle a Samba upgrade */
583 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
585 DEBUG(10, ("Fresh database\n"));
586 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
587 vers_id = NTDRIVERS_DATABASE_VERSION_5;
590 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
592 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
593 if (!upgrade_to_version_3())
595 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
596 vers_id = NTDRIVERS_DATABASE_VERSION_3;
599 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
600 /* Written on a bigendian machine with old fetch_int code. Save as le. */
601 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
602 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
603 vers_id = NTDRIVERS_DATABASE_VERSION_3;
606 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
607 if ( !upgrade_to_version_4() )
609 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
610 vers_id = NTDRIVERS_DATABASE_VERSION_4;
613 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
614 if ( !upgrade_to_version_5() )
616 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
617 vers_id = NTDRIVERS_DATABASE_VERSION_5;
621 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
622 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
627 update_c_setprinter(True);
630 * register callback to handle updating printers as new
631 * drivers are installed
634 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
635 do_drv_upgrade_printer);
638 * register callback to handle updating printer data
639 * when a driver is initialized
642 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
643 reset_all_printerdata);
645 /* of course, none of the message callbacks matter if you don't
646 tell messages.c that you interested in receiving PRINT_GENERAL
647 msgs. This is done in claim_connection() */
650 if ( lp_security() == SEC_ADS ) {
651 win_rc = check_published_printers();
652 if (!W_ERROR_IS_OK(win_rc))
653 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
659 /*******************************************************************
660 Function to allow filename parsing "the old way".
661 ********************************************************************/
663 static void driver_unix_convert(char *name,connection_struct *conn,
664 char *saved_last_component, SMB_STRUCT_STAT *pst)
667 unix_clean_name(name);
668 trim_string(name,"/","/");
669 unix_convert(conn, name, False, saved_last_component, pst);
672 /*******************************************************************
673 tdb traversal function for counting printers.
674 ********************************************************************/
676 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
677 TDB_DATA data, void *context)
679 int *printer_count = (int*)context;
681 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
683 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
689 /*******************************************************************
690 Update the spooler global c_setprinter. This variable is initialized
691 when the parent smbd starts with the number of existing printers. It
692 is monotonically increased by the current number of printers *after*
693 each add or delete printer RPC. Only Microsoft knows why... JRR020119
694 ********************************************************************/
696 uint32 update_c_setprinter(BOOL initialize)
699 int32 printer_count = 0;
701 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
703 /* Traverse the tdb, counting the printers */
704 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
706 /* If initializing, set c_setprinter to current printers count
707 * otherwise, bump it by the current printer count
710 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
712 c_setprinter = printer_count;
714 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
715 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
717 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
719 return (uint32)c_setprinter;
722 /*******************************************************************
723 Get the spooler global c_setprinter, accounting for initialization.
724 ********************************************************************/
726 uint32 get_c_setprinter(void)
728 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
730 if (c_setprinter == (int32)-1)
731 c_setprinter = update_c_setprinter(True);
733 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
735 return (uint32)c_setprinter;
738 /****************************************************************************
739 Get builtin form struct list.
740 ****************************************************************************/
742 int get_builtin_ntforms(nt_forms_struct **list)
744 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
748 return sizeof(default_forms) / sizeof(default_forms[0]);
751 /****************************************************************************
752 get a builtin form struct
753 ****************************************************************************/
755 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
759 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
760 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
761 count = sizeof(default_forms) / sizeof(default_forms[0]);
762 for (i=0;i<count;i++) {
763 if (strequal(form_name,default_forms[i].name)) {
764 DEBUGADD(6,("Found builtin form %s \n", form_name));
765 memcpy(form,&default_forms[i],sizeof(*form));
773 /****************************************************************************
774 get a form struct list.
775 ****************************************************************************/
777 int get_ntforms(nt_forms_struct **list)
779 TDB_DATA kbuf, newkey, dbuf;
780 nt_forms_struct form;
787 for (kbuf = tdb_firstkey(tdb_forms);
789 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
791 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
794 dbuf = tdb_fetch(tdb_forms, kbuf);
798 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
799 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
800 &i, &form.flag, &form.width, &form.length, &form.left,
801 &form.top, &form.right, &form.bottom);
802 SAFE_FREE(dbuf.dptr);
803 if (ret != dbuf.dsize)
806 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
808 DEBUG(0,("get_ntforms: Realloc fail.\n"));
819 /****************************************************************************
820 write a form struct list
821 ****************************************************************************/
822 int write_ntforms(nt_forms_struct **list, int number)
829 for (i=0;i<number;i++) {
830 /* save index, so list is rebuilt in correct order */
831 len = tdb_pack((uint8 *)buf, sizeof(buf), "dddddddd",
832 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
833 (*list)[i].left, (*list)[i].top, (*list)[i].right,
835 if (len > sizeof(buf)) break;
836 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
838 dbuf.dptr = (uint8 *)buf;
839 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) break;
845 /****************************************************************************
846 add a form struct at the end of the list
847 ****************************************************************************/
848 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
855 * NT tries to add forms even when
856 * they are already in the base
857 * only update the values if already present
862 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
863 for (n=0; n<*count; n++) {
864 if ( strequal((*list)[n].name, form_name) ) {
871 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
872 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
875 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
879 (*list)[n].flag=form->flags;
880 (*list)[n].width=form->size_x;
881 (*list)[n].length=form->size_y;
882 (*list)[n].left=form->left;
883 (*list)[n].top=form->top;
884 (*list)[n].right=form->right;
885 (*list)[n].bottom=form->bottom;
887 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
888 update ? "updated" : "added", form_name));
893 /****************************************************************************
894 Delete a named form struct.
895 ****************************************************************************/
897 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
905 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
907 for (n=0; n<*count; n++) {
908 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
909 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
915 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
916 *ret = WERR_INVALID_PARAM;
920 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
921 if (tdb_delete_bystring(tdb_forms, key) != 0) {
929 /****************************************************************************
930 Update a form struct.
931 ****************************************************************************/
933 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
937 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
939 DEBUG(106, ("[%s]\n", form_name));
940 for (n=0; n<count; n++) {
941 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
942 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
946 if (n==count) return;
948 (*list)[n].flag=form->flags;
949 (*list)[n].width=form->size_x;
950 (*list)[n].length=form->size_y;
951 (*list)[n].left=form->left;
952 (*list)[n].top=form->top;
953 (*list)[n].right=form->right;
954 (*list)[n].bottom=form->bottom;
957 /****************************************************************************
958 Get the nt drivers list.
959 Traverse the database and look-up the matching names.
960 ****************************************************************************/
961 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
964 const char *short_archi;
966 TDB_DATA kbuf, newkey;
968 short_archi = get_short_archi(architecture);
973 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
975 for (kbuf = tdb_firstkey(tdb_drivers);
977 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
979 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
982 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
983 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
987 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
994 /****************************************************************************
995 Function to do the mapping between the long architecture name and
997 ****************************************************************************/
999 const char *get_short_archi(const char *long_archi)
1003 DEBUG(107,("Getting architecture dependant directory\n"));
1006 } while ( (archi_table[i].long_archi!=NULL ) &&
1007 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1009 if (archi_table[i].long_archi==NULL) {
1010 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1014 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1016 DEBUGADD(108,("index: [%d]\n", i));
1017 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1018 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1020 return archi_table[i].short_archi;
1023 /****************************************************************************
1024 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1025 There are two case to be covered here: PE (Portable Executable) and NE (New
1026 Executable) files. Both files support the same INFO structure, but PE files
1027 store the signature in unicode, and NE files store it as !unicode.
1028 returns -1 on error, 1 on version info found, and 0 on no version info found.
1029 ****************************************************************************/
1031 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1037 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1038 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1039 fname, DOS_HEADER_SIZE));
1043 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1044 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1045 fname, (unsigned long)byte_count));
1046 goto no_version_info;
1049 /* Is this really a DOS header? */
1050 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1051 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1052 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1053 goto no_version_info;
1056 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1057 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1058 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1060 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1061 goto no_version_info;
1064 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1065 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1066 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1067 fname, (unsigned long)byte_count));
1068 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1069 goto no_version_info;
1072 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1073 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1074 unsigned int num_sections;
1075 unsigned int section_table_bytes;
1077 /* Just skip over optional header to get to section table */
1078 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
1079 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1080 SEEK_CUR) == (SMB_OFF_T)-1) {
1081 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1086 /* get the section table */
1087 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1088 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1089 if (section_table_bytes == 0)
1093 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1094 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1095 fname, section_table_bytes));
1099 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1100 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1101 fname, (unsigned long)byte_count));
1105 /* Iterate the section table looking for the resource section ".rsrc" */
1106 for (i = 0; i < num_sections; i++) {
1107 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1109 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1110 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1111 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1113 if (section_bytes == 0)
1117 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1118 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1119 fname, section_bytes));
1123 /* Seek to the start of the .rsrc section info */
1124 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1125 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1130 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1131 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1132 fname, (unsigned long)byte_count));
1136 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1139 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1140 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1141 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1142 /* Align to next long address */
1143 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1145 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1146 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1147 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1149 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1150 fname, *major, *minor,
1151 (*major>>16)&0xffff, *major&0xffff,
1152 (*minor>>16)&0xffff, *minor&0xffff));
1161 /* Version info not found, fall back to origin date/time */
1162 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1166 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1167 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1168 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1169 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1170 /* At this point, we assume the file is in error. It still could be somthing
1171 * else besides a NE file, but it unlikely at this point. */
1175 /* Allocate a bit more space to speed up things */
1177 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1178 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1179 fname, PE_HEADER_SIZE));
1183 /* This is a HACK! I got tired of trying to sort through the messy
1184 * 'NE' file format. If anyone wants to clean this up please have at
1185 * it, but this works. 'NE' files will eventually fade away. JRR */
1186 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1187 /* Cover case that should not occur in a well formed 'NE' .dll file */
1188 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1190 for(i=0; i<byte_count; i++) {
1191 /* Fast skip past data that can't possibly match */
1192 if (buf[i] != 'V') continue;
1194 /* Potential match data crosses buf boundry, move it to beginning
1195 * of buf, and fill the buf with as much as it will hold. */
1196 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1199 memcpy(buf, &buf[i], byte_count-i);
1200 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1201 (byte_count-i))) < 0) {
1203 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1208 byte_count = bc + (byte_count - i);
1209 if (byte_count<VS_VERSION_INFO_SIZE) break;
1214 /* Check that the full signature string and the magic number that
1215 * follows exist (not a perfect solution, but the chances that this
1216 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1217 * twice, as it is simpler to read the code. */
1218 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1219 /* Compute skip alignment to next long address */
1220 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1221 sizeof(VS_SIGNATURE)) & 3;
1222 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1224 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1225 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1226 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1227 fname, *major, *minor,
1228 (*major>>16)&0xffff, *major&0xffff,
1229 (*minor>>16)&0xffff, *minor&0xffff));
1236 /* Version info not found, fall back to origin date/time */
1237 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1242 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1243 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1244 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1255 /****************************************************************************
1256 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1257 share one or more files. During the MS installation process files are checked
1258 to insure that only a newer version of a shared file is installed over an
1259 older version. There are several possibilities for this comparison. If there
1260 is no previous version, the new one is newer (obviously). If either file is
1261 missing the version info structure, compare the creation date (on Unix use
1262 the modification date). Otherwise chose the numerically larger version number.
1263 ****************************************************************************/
1265 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1267 BOOL use_version = True;
1272 time_t new_create_time;
1276 time_t old_create_time;
1278 files_struct *fsp = NULL;
1280 SMB_STRUCT_STAT stat_buf;
1284 SET_STAT_INVALID(st);
1285 SET_STAT_INVALID(stat_buf);
1286 new_create_time = (time_t)0;
1287 old_create_time = (time_t)0;
1289 /* Get file version info (if available) for previous file (if it exists) */
1290 pstrcpy(filepath, old_file);
1292 driver_unix_convert(filepath,conn,NULL,&stat_buf);
1294 status = open_file_ntcreate(conn, filepath, &stat_buf,
1296 FILE_SHARE_READ|FILE_SHARE_WRITE,
1299 FILE_ATTRIBUTE_NORMAL,
1303 if (!NT_STATUS_IS_OK(status)) {
1304 /* Old file not found, so by definition new file is in fact newer */
1305 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1310 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1316 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1318 use_version = False;
1319 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1320 old_create_time = st.st_mtime;
1321 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1324 close_file(fsp, NORMAL_CLOSE);
1326 /* Get file version info (if available) for new file */
1327 pstrcpy(filepath, new_file);
1328 driver_unix_convert(filepath,conn,NULL,&stat_buf);
1330 status = open_file_ntcreate(conn, filepath, &stat_buf,
1332 FILE_SHARE_READ|FILE_SHARE_WRITE,
1335 FILE_ATTRIBUTE_NORMAL,
1339 if (!NT_STATUS_IS_OK(status)) {
1340 /* New file not found, this shouldn't occur if the caller did its job */
1341 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1346 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1352 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1354 use_version = False;
1355 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1356 new_create_time = st.st_mtime;
1357 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1360 close_file(fsp, NORMAL_CLOSE);
1362 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1363 /* Compare versions and choose the larger version number */
1364 if (new_major > old_major ||
1365 (new_major == old_major && new_minor > old_minor)) {
1367 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1371 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1376 /* Compare modification time/dates and choose the newest time/date */
1377 if (new_create_time > old_create_time) {
1378 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1382 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1389 close_file(fsp, NORMAL_CLOSE);
1393 /****************************************************************************
1394 Determine the correct cVersion associated with an architecture and driver
1395 ****************************************************************************/
1396 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1397 struct current_user *user, WERROR *perr)
1404 files_struct *fsp = NULL;
1406 connection_struct *conn;
1409 SET_STAT_INVALID(st);
1411 *perr = WERR_INVALID_PARAM;
1413 /* If architecture is Windows 95/98/ME, the version is always 0. */
1414 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1415 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1420 /* If architecture is Windows x64, the version is always 3. */
1421 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1422 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1428 * Connect to the print$ share under the same account as the user connected
1429 * to the rpc pipe. Note we must still be root to do this.
1432 /* Null password is ok - we are already an authenticated user... */
1433 null_pw = data_blob_null;
1434 fstrcpy(res_type, "A:");
1436 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1440 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1441 *perr = ntstatus_to_werror(nt_status);
1445 /* We are temporarily becoming the connection user. */
1446 if (!become_user(conn, user->vuid)) {
1447 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1448 *perr = WERR_ACCESS_DENIED;
1452 /* Open the driver file (Portable Executable format) and determine the
1453 * deriver the cversion. */
1454 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1456 driver_unix_convert(driverpath,conn,NULL,&st);
1458 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1459 *perr = WERR_BADFILE;
1463 status = open_file_ntcreate(conn, driverpath, &st,
1465 FILE_SHARE_READ|FILE_SHARE_WRITE,
1468 FILE_ATTRIBUTE_NORMAL,
1472 if (!NT_STATUS_IS_OK(status)) {
1473 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1474 driverpath, errno));
1475 *perr = WERR_ACCESS_DENIED;
1480 int ret = get_file_version(fsp, driverpath, &major, &minor);
1481 if (ret == -1) goto error_exit;
1484 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1489 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1490 * for more details. Version in this case is not just the version of the
1491 * file, but the version in the sense of kernal mode (2) vs. user mode
1492 * (3) drivers. Other bits of the version fields are the version info.
1495 cversion = major & 0x0000ffff;
1497 case 2: /* WinNT drivers */
1498 case 3: /* Win2K drivers */
1502 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1503 driverpath, cversion));
1507 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1508 driverpath, major, minor));
1511 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1512 driverpath, cversion));
1514 close_file(fsp, NORMAL_CLOSE);
1515 close_cnum(conn, user->vuid);
1524 close_file(fsp, NORMAL_CLOSE);
1526 close_cnum(conn, user->vuid);
1531 /****************************************************************************
1532 ****************************************************************************/
1533 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1534 struct current_user *user)
1536 const char *architecture;
1542 /* clean up the driver name.
1543 * we can get .\driver.dll
1544 * or worse c:\windows\system\driver.dll !
1546 /* using an intermediate string to not have overlaping memcpy()'s */
1547 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1548 fstrcpy(new_name, p+1);
1549 fstrcpy(driver->driverpath, new_name);
1552 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1553 fstrcpy(new_name, p+1);
1554 fstrcpy(driver->datafile, new_name);
1557 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1558 fstrcpy(new_name, p+1);
1559 fstrcpy(driver->configfile, new_name);
1562 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1563 fstrcpy(new_name, p+1);
1564 fstrcpy(driver->helpfile, new_name);
1567 if (driver->dependentfiles) {
1568 for (i=0; *driver->dependentfiles[i]; i++) {
1569 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1570 fstrcpy(new_name, p+1);
1571 fstrcpy(driver->dependentfiles[i], new_name);
1576 architecture = get_short_archi(driver->environment);
1577 if (!architecture) {
1578 return WERR_UNKNOWN_PRINTER_DRIVER;
1581 /* jfm:7/16/2000 the client always sends the cversion=0.
1582 * The server should check which version the driver is by reading
1583 * the PE header of driver->driverpath.
1585 * For Windows 95/98 the version is 0 (so the value sent is correct)
1586 * For Windows NT (the architecture doesn't matter)
1587 * NT 3.1: cversion=0
1588 * NT 3.5/3.51: cversion=1
1592 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1598 /****************************************************************************
1599 ****************************************************************************/
1600 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1602 const char *architecture;
1608 /* clean up the driver name.
1609 * we can get .\driver.dll
1610 * or worse c:\windows\system\driver.dll !
1612 /* using an intermediate string to not have overlaping memcpy()'s */
1613 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1614 fstrcpy(new_name, p+1);
1615 fstrcpy(driver->driverpath, new_name);
1618 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1619 fstrcpy(new_name, p+1);
1620 fstrcpy(driver->datafile, new_name);
1623 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1624 fstrcpy(new_name, p+1);
1625 fstrcpy(driver->configfile, new_name);
1628 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1629 fstrcpy(new_name, p+1);
1630 fstrcpy(driver->helpfile, new_name);
1633 if (driver->dependentfiles) {
1634 for (i=0; *driver->dependentfiles[i]; i++) {
1635 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1636 fstrcpy(new_name, p+1);
1637 fstrcpy(driver->dependentfiles[i], new_name);
1642 architecture = get_short_archi(driver->environment);
1643 if (!architecture) {
1644 return WERR_UNKNOWN_PRINTER_DRIVER;
1647 /* jfm:7/16/2000 the client always sends the cversion=0.
1648 * The server should check which version the driver is by reading
1649 * the PE header of driver->driverpath.
1651 * For Windows 95/98 the version is 0 (so the value sent is correct)
1652 * For Windows NT (the architecture doesn't matter)
1653 * NT 3.1: cversion=0
1654 * NT 3.5/3.51: cversion=1
1659 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1665 /****************************************************************************
1666 ****************************************************************************/
1667 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1668 uint32 level, struct current_user *user)
1673 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1674 driver=driver_abstract.info_3;
1675 return clean_up_driver_struct_level_3(driver, user);
1679 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1680 driver=driver_abstract.info_6;
1681 return clean_up_driver_struct_level_6(driver, user);
1684 return WERR_INVALID_PARAM;
1688 /****************************************************************************
1689 This function sucks and should be replaced. JRA.
1690 ****************************************************************************/
1692 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1694 dst->cversion = src->version;
1696 fstrcpy( dst->name, src->name);
1697 fstrcpy( dst->environment, src->environment);
1698 fstrcpy( dst->driverpath, src->driverpath);
1699 fstrcpy( dst->datafile, src->datafile);
1700 fstrcpy( dst->configfile, src->configfile);
1701 fstrcpy( dst->helpfile, src->helpfile);
1702 fstrcpy( dst->monitorname, src->monitorname);
1703 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1704 dst->dependentfiles = src->dependentfiles;
1707 #if 0 /* Debugging function */
1709 static char* ffmt(unsigned char *c){
1711 static char ffmt_str[17];
1713 for (i=0; i<16; i++) {
1714 if ((c[i] < ' ') || (c[i] > '~'))
1725 /****************************************************************************
1726 ****************************************************************************/
1727 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1728 struct current_user *user, WERROR *perr)
1730 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1731 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1732 const char *architecture;
1737 connection_struct *conn;
1746 memset(inbuf, '\0', sizeof(inbuf));
1747 memset(outbuf, '\0', sizeof(outbuf));
1751 driver=driver_abstract.info_3;
1752 else if (level==6) {
1753 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1754 driver = &converted_driver;
1756 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1757 return WERR_UNKNOWN_LEVEL;
1760 architecture = get_short_archi(driver->environment);
1761 if (!architecture) {
1762 return WERR_UNKNOWN_PRINTER_DRIVER;
1766 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1767 * Note we must be root to do this.
1770 null_pw = data_blob_null;
1771 fstrcpy(res_type, "A:");
1773 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1777 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1778 *perr = ntstatus_to_werror(nt_status);
1779 return WERR_NO_SUCH_SHARE;
1783 * Save who we are - we are temporarily becoming the connection user.
1786 if (!become_user(conn, conn->vuid)) {
1787 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1788 return WERR_ACCESS_DENIED;
1792 * make the directories version and version\driver_name
1793 * under the architecture directory.
1795 DEBUG(5,("Creating first directory\n"));
1796 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1797 driver_unix_convert(new_dir, conn, NULL, &st);
1798 create_directory(conn, new_dir);
1800 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1801 * listed for this driver which has already been moved, skip it (note:
1802 * drivers may list the same file name several times. Then check if the
1803 * file already exists in archi\cversion\, if so, check that the version
1804 * info (or time stamps if version info is unavailable) is newer (or the
1805 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1806 * Otherwise, delete the file.
1808 * If a file is not moved to archi\cversion\ because of an error, all the
1809 * rest of the 'unmoved' driver files are removed from archi\. If one or
1810 * more of the driver's files was already moved to archi\cversion\, it
1811 * potentially leaves the driver in a partially updated state. Version
1812 * trauma will most likely occur if an client attempts to use any printer
1813 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1814 * done is appropriate... later JRR
1817 DEBUG(5,("Moving files now !\n"));
1819 if (driver->driverpath && strlen(driver->driverpath)) {
1820 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1821 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1822 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1823 driver_unix_convert(new_name, conn, NULL, &st);
1824 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1825 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1826 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1827 new_name, old_name));
1828 *perr = WERR_ACCESS_DENIED;
1834 if (driver->datafile && strlen(driver->datafile)) {
1835 if (!strequal(driver->datafile, driver->driverpath)) {
1836 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1837 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1838 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1839 driver_unix_convert(new_name, conn, NULL, &st);
1840 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1841 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1842 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1843 new_name, old_name));
1844 *perr = WERR_ACCESS_DENIED;
1851 if (driver->configfile && strlen(driver->configfile)) {
1852 if (!strequal(driver->configfile, driver->driverpath) &&
1853 !strequal(driver->configfile, driver->datafile)) {
1854 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1855 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1856 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1857 driver_unix_convert(new_name, conn, NULL, &st);
1858 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1859 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1860 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1861 new_name, old_name));
1862 *perr = WERR_ACCESS_DENIED;
1869 if (driver->helpfile && strlen(driver->helpfile)) {
1870 if (!strequal(driver->helpfile, driver->driverpath) &&
1871 !strequal(driver->helpfile, driver->datafile) &&
1872 !strequal(driver->helpfile, driver->configfile)) {
1873 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1874 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1875 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1876 driver_unix_convert(new_name, conn, NULL, &st);
1877 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1878 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1879 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1880 new_name, old_name));
1881 *perr = WERR_ACCESS_DENIED;
1888 if (driver->dependentfiles) {
1889 for (i=0; *driver->dependentfiles[i]; i++) {
1890 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1891 !strequal(driver->dependentfiles[i], driver->datafile) &&
1892 !strequal(driver->dependentfiles[i], driver->configfile) &&
1893 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1895 for (j=0; j < i; j++) {
1896 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1901 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1902 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1903 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1904 driver_unix_convert(new_name, conn, NULL, &st);
1905 if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
1906 OPENX_FILE_EXISTS_TRUNCATE|
1907 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1908 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1909 new_name, old_name));
1910 *perr = WERR_ACCESS_DENIED;
1919 close_cnum(conn, user->vuid);
1922 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1925 /****************************************************************************
1926 ****************************************************************************/
1927 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1930 const char *architecture;
1938 architecture = get_short_archi(driver->environment);
1939 if (!architecture) {
1943 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1944 * \\server is added in the rpc server layer.
1945 * It does make sense to NOT store the server's name in the printer TDB.
1948 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1950 /* .inf files do not always list a file for each of the four standard files.
1951 * Don't prepend a path to a null filename, or client claims:
1952 * "The server on which the printer resides does not have a suitable
1953 * <printer driver name> printer driver installed. Click OK if you
1954 * wish to install the driver on your local machine."
1956 if (strlen(driver->driverpath)) {
1957 fstrcpy(temp_name, driver->driverpath);
1958 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1961 if (strlen(driver->datafile)) {
1962 fstrcpy(temp_name, driver->datafile);
1963 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1966 if (strlen(driver->configfile)) {
1967 fstrcpy(temp_name, driver->configfile);
1968 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1971 if (strlen(driver->helpfile)) {
1972 fstrcpy(temp_name, driver->helpfile);
1973 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1976 if (driver->dependentfiles) {
1977 for (i=0; *driver->dependentfiles[i]; i++) {
1978 fstrcpy(temp_name, driver->dependentfiles[i]);
1979 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1983 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1985 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1992 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1995 driver->environment,
2000 driver->monitorname,
2001 driver->defaultdatatype);
2003 if (driver->dependentfiles) {
2004 for (i=0; *driver->dependentfiles[i]; i++) {
2005 len += tdb_pack(buf+len, buflen-len, "f",
2006 driver->dependentfiles[i]);
2010 if (len != buflen) {
2011 buf = (uint8 *)SMB_REALLOC(buf, len);
2013 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2024 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2028 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2034 /****************************************************************************
2035 ****************************************************************************/
2036 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2038 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2041 info3.cversion = driver->version;
2042 fstrcpy(info3.name,driver->name);
2043 fstrcpy(info3.environment,driver->environment);
2044 fstrcpy(info3.driverpath,driver->driverpath);
2045 fstrcpy(info3.datafile,driver->datafile);
2046 fstrcpy(info3.configfile,driver->configfile);
2047 fstrcpy(info3.helpfile,driver->helpfile);
2048 fstrcpy(info3.monitorname,driver->monitorname);
2049 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2050 info3.dependentfiles = driver->dependentfiles;
2052 return add_a_printer_driver_3(&info3);
2056 /****************************************************************************
2057 ****************************************************************************/
2058 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2060 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2064 fstrcpy(info.name, driver);
2065 fstrcpy(info.defaultdatatype, "RAW");
2067 fstrcpy(info.driverpath, "");
2068 fstrcpy(info.datafile, "");
2069 fstrcpy(info.configfile, "");
2070 fstrcpy(info.helpfile, "");
2072 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2075 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2076 fstrcpy(info.dependentfiles[0], "");
2078 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2080 SAFE_FREE(info.dependentfiles);
2087 /****************************************************************************
2088 ****************************************************************************/
2089 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2091 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2093 const char *architecture;
2098 ZERO_STRUCT(driver);
2100 architecture = get_short_archi(arch);
2101 if ( !architecture ) {
2102 return WERR_UNKNOWN_PRINTER_DRIVER;
2105 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2107 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2110 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2112 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2114 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2116 return WERR_UNKNOWN_PRINTER_DRIVER;
2118 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2127 driver.defaultdatatype);
2130 while (len < dbuf.dsize) {
2131 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2132 if ( !driver.dependentfiles ) {
2133 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2137 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2138 &driver.dependentfiles[i]);
2142 if ( driver.dependentfiles )
2143 fstrcpy( driver.dependentfiles[i], "" );
2145 SAFE_FREE(dbuf.dptr);
2147 if (len != dbuf.dsize) {
2148 SAFE_FREE(driver.dependentfiles);
2150 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2153 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2155 SAFE_FREE(driver.dependentfiles);
2162 /****************************************************************************
2163 Debugging function, dump at level 6 the struct in the logs.
2164 ****************************************************************************/
2166 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2169 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2172 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2178 if (driver.info_3 == NULL)
2181 info3=driver.info_3;
2183 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2184 DEBUGADD(20,("name:[%s]\n", info3->name));
2185 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2186 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2187 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2188 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2189 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2190 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2191 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2193 for (i=0; info3->dependentfiles &&
2194 *info3->dependentfiles[i]; i++) {
2195 DEBUGADD(20,("dependentfile:[%s]\n",
2196 info3->dependentfiles[i]));
2203 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2211 /****************************************************************************
2212 ****************************************************************************/
2213 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2217 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2222 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2223 nt_devmode->devicename,
2224 nt_devmode->formname,
2226 nt_devmode->specversion,
2227 nt_devmode->driverversion,
2229 nt_devmode->driverextra,
2230 nt_devmode->orientation,
2231 nt_devmode->papersize,
2232 nt_devmode->paperlength,
2233 nt_devmode->paperwidth,
2236 nt_devmode->defaultsource,
2237 nt_devmode->printquality,
2240 nt_devmode->yresolution,
2241 nt_devmode->ttoption,
2242 nt_devmode->collate,
2243 nt_devmode->logpixels,
2246 nt_devmode->bitsperpel,
2247 nt_devmode->pelswidth,
2248 nt_devmode->pelsheight,
2249 nt_devmode->displayflags,
2250 nt_devmode->displayfrequency,
2251 nt_devmode->icmmethod,
2252 nt_devmode->icmintent,
2253 nt_devmode->mediatype,
2254 nt_devmode->dithertype,
2255 nt_devmode->reserved1,
2256 nt_devmode->reserved2,
2257 nt_devmode->panningwidth,
2258 nt_devmode->panningheight,
2259 nt_devmode->nt_dev_private);
2262 if (nt_devmode->nt_dev_private) {
2263 len += tdb_pack(buf+len, buflen-len, "B",
2264 nt_devmode->driverextra,
2265 nt_devmode->nt_dev_private);
2268 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2273 /****************************************************************************
2274 Pack all values in all printer keys
2275 ***************************************************************************/
2277 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2281 REGISTRY_VALUE *val;
2282 REGVAL_CTR *val_ctr;
2289 /* loop over all keys */
2291 for ( i=0; i<data->num_keys; i++ ) {
2292 val_ctr = data->keys[i].values;
2293 num_values = regval_ctr_numvals( val_ctr );
2295 /* pack the keyname followed by a empty value */
2297 len += tdb_pack(buf+len, buflen-len, "pPdB",
2298 &data->keys[i].name,
2304 /* now loop over all values */
2306 for ( j=0; j<num_values; j++ ) {
2307 /* pathname should be stored as <key>\<value> */
2309 val = regval_ctr_specific_value( val_ctr, j );
2310 pstrcpy( path, data->keys[i].name );
2311 pstrcat( path, "\\" );
2312 pstrcat( path, regval_name(val) );
2314 len += tdb_pack(buf+len, buflen-len, "pPdB",
2319 regval_data_p(val) );
2321 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2328 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2334 /****************************************************************************
2335 Delete a printer - this just deletes the printer info file, any open
2336 handles are not affected.
2337 ****************************************************************************/
2339 uint32 del_a_printer(const char *sharename)
2342 pstring printdb_path;
2344 kbuf = make_printer_tdbkey( sharename );
2345 tdb_delete(tdb_printers, kbuf);
2347 kbuf= make_printers_secdesc_tdbkey( sharename );
2348 tdb_delete(tdb_printers, kbuf);
2350 close_all_print_db();
2352 if (geteuid() == 0) {
2353 pstrcpy(printdb_path, lock_path("printing/"));
2354 pstrcat(printdb_path, sharename);
2355 pstrcat(printdb_path, ".tdb");
2357 unlink(printdb_path);
2363 /****************************************************************************
2364 ****************************************************************************/
2365 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2370 TDB_DATA kbuf, dbuf;
2373 * in addprinter: no servername and the printer is the name
2374 * in setprinter: servername is \\server
2375 * and printer is \\server\\printer
2377 * Samba manages only local printers.
2378 * we currently don't support things like i
2379 * path=\\other_server\printer
2381 * We only store the printername, not \\server\printername
2384 if ( info->servername[0] != '\0' ) {
2385 trim_string(info->printername, info->servername, NULL);
2386 trim_char(info->printername, '\\', '\0');
2387 info->servername[0]='\0';
2391 * JFM: one day I'll forget.
2392 * below that's info->portname because that's the SAMBA sharename
2393 * and I made NT 'thinks' it's the portname
2394 * the info->sharename is the thing you can name when you add a printer
2395 * that's the short-name when you create shared printer for 95/98
2396 * So I've made a limitation in SAMBA: you can only have 1 printer model
2397 * behind a SAMBA share.
2405 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2408 info->default_priority,
2425 info->printprocessor,
2429 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2431 len += pack_values( info->data, buf+len, buflen-len );
2433 if (buflen != len) {
2434 buf = (uint8 *)SMB_REALLOC(buf, len);
2436 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2445 kbuf = make_printer_tdbkey( info->sharename );
2450 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2453 if (!W_ERROR_IS_OK(ret))
2454 DEBUG(8, ("error updating printer to tdb on disk\n"));
2458 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2459 info->sharename, info->drivername, info->portname, len));
2465 /****************************************************************************
2466 Malloc and return an NT devicemode.
2467 ****************************************************************************/
2469 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2472 char adevice[MAXDEVICENAME];
2473 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2475 if (nt_devmode == NULL) {
2476 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2480 ZERO_STRUCTP(nt_devmode);
2482 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2483 fstrcpy(nt_devmode->devicename, adevice);
2485 fstrcpy(nt_devmode->formname, "Letter");
2487 nt_devmode->specversion = 0x0401;
2488 nt_devmode->driverversion = 0x0400;
2489 nt_devmode->size = 0x00DC;
2490 nt_devmode->driverextra = 0x0000;
2491 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2492 DEFAULTSOURCE | COPIES | SCALE |
2493 PAPERSIZE | ORIENTATION;
2494 nt_devmode->orientation = 1;
2495 nt_devmode->papersize = PAPER_LETTER;
2496 nt_devmode->paperlength = 0;
2497 nt_devmode->paperwidth = 0;
2498 nt_devmode->scale = 0x64;
2499 nt_devmode->copies = 1;
2500 nt_devmode->defaultsource = BIN_FORMSOURCE;
2501 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2502 nt_devmode->color = COLOR_MONOCHROME;
2503 nt_devmode->duplex = DUP_SIMPLEX;
2504 nt_devmode->yresolution = 0;
2505 nt_devmode->ttoption = TT_SUBDEV;
2506 nt_devmode->collate = COLLATE_FALSE;
2507 nt_devmode->icmmethod = 0;
2508 nt_devmode->icmintent = 0;
2509 nt_devmode->mediatype = 0;
2510 nt_devmode->dithertype = 0;
2512 /* non utilisés par un driver d'imprimante */
2513 nt_devmode->logpixels = 0;
2514 nt_devmode->bitsperpel = 0;
2515 nt_devmode->pelswidth = 0;
2516 nt_devmode->pelsheight = 0;
2517 nt_devmode->displayflags = 0;
2518 nt_devmode->displayfrequency = 0;
2519 nt_devmode->reserved1 = 0;
2520 nt_devmode->reserved2 = 0;
2521 nt_devmode->panningwidth = 0;
2522 nt_devmode->panningheight = 0;
2524 nt_devmode->nt_dev_private = NULL;
2528 /****************************************************************************
2529 Deepcopy an NT devicemode.
2530 ****************************************************************************/
2532 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2534 NT_DEVICEMODE *new_nt_devicemode = NULL;
2536 if ( !nt_devicemode )
2539 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2540 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2544 new_nt_devicemode->nt_dev_private = NULL;
2545 if (nt_devicemode->nt_dev_private != NULL) {
2546 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2547 SAFE_FREE(new_nt_devicemode);
2548 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2553 return new_nt_devicemode;
2556 /****************************************************************************
2557 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2558 ****************************************************************************/
2560 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2562 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2564 if(nt_devmode == NULL)
2567 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2569 SAFE_FREE(nt_devmode->nt_dev_private);
2570 SAFE_FREE(*devmode_ptr);
2573 /****************************************************************************
2574 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2575 ****************************************************************************/
2577 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2579 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2584 free_nt_devicemode(&info->devmode);
2586 TALLOC_FREE( *info_ptr );
2590 /****************************************************************************
2591 ****************************************************************************/
2592 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2596 NT_DEVICEMODE devmode;
2598 ZERO_STRUCT(devmode);
2600 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2602 if (!*nt_devmode) return len;
2604 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2608 &devmode.specversion,
2609 &devmode.driverversion,
2611 &devmode.driverextra,
2612 &devmode.orientation,
2614 &devmode.paperlength,
2615 &devmode.paperwidth,
2618 &devmode.defaultsource,
2619 &devmode.printquality,
2622 &devmode.yresolution,
2628 &devmode.bitsperpel,
2630 &devmode.pelsheight,
2631 &devmode.displayflags,
2632 &devmode.displayfrequency,
2636 &devmode.dithertype,
2639 &devmode.panningwidth,
2640 &devmode.panningheight,
2641 &devmode.nt_dev_private);
2643 if (devmode.nt_dev_private) {
2644 /* the len in tdb_unpack is an int value and
2645 * devmode.driverextra is only a short
2647 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2648 devmode.driverextra=(uint16)extra_len;
2650 /* check to catch an invalid TDB entry so we don't segfault */
2651 if (devmode.driverextra == 0) {
2652 devmode.nt_dev_private = NULL;
2656 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2658 SAFE_FREE(devmode.nt_dev_private);
2662 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2663 if (devmode.nt_dev_private)
2664 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2669 /****************************************************************************
2670 Allocate and initialize a new slot.
2671 ***************************************************************************/
2673 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2678 if ( !name || !data )
2681 /* allocate another slot in the NT_PRINTER_KEY array */
2683 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2684 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2690 key_index = data->num_keys;
2692 /* initialze new key */
2694 data->keys[key_index].name = talloc_strdup( data, name );
2696 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2701 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2706 /****************************************************************************
2707 search for a registry key name in the existing printer data
2708 ***************************************************************************/
2710 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2714 for ( i=0; i<data->num_keys; i++ ) {
2715 if ( strequal( data->keys[i].name, name ) ) {
2717 /* cleanup memory */
2719 TALLOC_FREE( data->keys[i].name );
2720 TALLOC_FREE( data->keys[i].values );
2722 /* if not the end of the array, move remaining elements down one slot */
2725 if ( data->num_keys && (i < data->num_keys) )
2726 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2733 return data->num_keys;
2736 /****************************************************************************
2737 search for a registry key name in the existing printer data
2738 ***************************************************************************/
2740 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2745 if ( !data || !name )
2748 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2750 /* loop over all existing keys */
2752 for ( i=0; i<data->num_keys; i++ ) {
2753 if ( strequal(data->keys[i].name, name) ) {
2754 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2764 /****************************************************************************
2765 ***************************************************************************/
2767 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2771 int num_subkeys = 0;
2773 fstring *subkeys_ptr = NULL;
2784 /* special case of asking for the top level printer data registry key names */
2786 if ( strlen(key) == 0 ) {
2787 for ( i=0; i<data->num_keys; i++ ) {
2789 /* found a match, so allocate space and copy the name */
2791 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2792 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2797 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2804 /* asking for the subkeys of some key */
2805 /* subkey paths are stored in the key name using '\' as the delimiter */
2807 for ( i=0; i<data->num_keys; i++ ) {
2808 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2810 /* if we found the exact key, then break */
2811 key_len = strlen( key );
2812 if ( strlen(data->keys[i].name) == key_len )
2815 /* get subkey path */
2817 p = data->keys[i].name + key_len;
2820 fstrcpy( subkeyname, p );
2821 if ( (p = strchr( subkeyname, '\\' )) )
2824 /* don't add a key more than once */
2826 for ( j=0; j<num_subkeys; j++ ) {
2827 if ( strequal( subkeys_ptr[j], subkeyname ) )
2831 if ( j != num_subkeys )
2834 /* found a match, so allocate space and copy the name */
2836 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2837 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2842 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2848 /* return error if the key was not found */
2850 if ( i == data->num_keys ) {
2851 SAFE_FREE(subkeys_ptr);
2856 /* tag off the end */
2859 fstrcpy(subkeys_ptr[num_subkeys], "" );
2861 *subkeys = subkeys_ptr;
2867 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2870 smb_ucs2_t conv_str[1024];
2873 regval_ctr_delvalue(ctr, val_name);
2874 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2875 STR_TERMINATE | STR_NOALIGN);
2876 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2877 (char *) conv_str, str_size);
2880 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2883 regval_ctr_delvalue(ctr, val_name);
2884 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2885 (char *) &dword, sizeof(dword));
2888 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2891 uint8 bin_bool = (b ? 1 : 0);
2892 regval_ctr_delvalue(ctr, val_name);
2893 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2894 (char *) &bin_bool, sizeof(bin_bool));
2897 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2898 const char *multi_sz)
2900 smb_ucs2_t *conv_strs = NULL;
2903 /* a multi-sz has to have a null string terminator, i.e., the last
2904 string must be followed by two nulls */
2905 str_size = strlen(multi_sz) + 2;
2906 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2911 /* Change to byte units. */
2912 str_size *= sizeof(smb_ucs2_t);
2913 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2914 STR_TERMINATE | STR_NOALIGN);
2916 regval_ctr_delvalue(ctr, val_name);
2917 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2918 (char *) conv_strs, str_size);
2919 safe_free(conv_strs);
2923 /****************************************************************************
2924 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2926 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2927 * @return BOOL indicating success or failure
2928 ***************************************************************************/
2930 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2932 REGVAL_CTR *ctr = NULL;
2935 char *allocated_string = NULL;
2936 const char *ascii_str;
2939 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2940 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2941 ctr = info2->data->keys[i].values;
2943 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2944 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2946 /* we make the assumption that the netbios name is the same
2947 as the DNS name sinc ethe former will be what we used to
2950 if ( get_mydnsdomname( dnssuffix ) )
2951 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2953 fstrcpy( longname, global_myname() );
2955 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2957 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2958 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2959 SAFE_FREE(allocated_string);
2961 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2962 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2963 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2964 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2965 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2966 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2967 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2968 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2969 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2971 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2972 (info2->attributes &
2973 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2975 switch (info2->attributes & 0x3) {
2977 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2980 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2983 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2986 ascii_str = "unknown";
2988 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2993 /*****************************************************************
2994 ****************************************************************/
2996 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3000 REGVAL_CTR *ctr=NULL;
3001 UNISTR2 unistr_guid;
3003 /* find the DsSpooler key */
3004 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3005 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3006 ctr = info2->data->keys[i].values;
3008 regval_ctr_delvalue(ctr, "objectGUID");
3010 /* We used to store this as a REG_BINARY but that causes
3013 ZERO_STRUCT( unistr_guid );
3014 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3015 UNI_STR_TERMINATE );
3017 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3018 (char *)unistr_guid.buffer,
3019 unistr_guid.uni_max_len*2);
3023 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3024 NT_PRINTER_INFO_LEVEL *printer)
3028 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3029 char *srv_dn_utf8, **srv_cn_utf8;
3032 const char *attrs[] = {"objectGUID", NULL};
3034 WERROR win_rc = WERR_OK;
3036 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3038 /* figure out where to publish */
3039 ads_find_machine_acct(ads, &res, global_myname());
3041 /* We use ldap_get_dn here as we need the answer
3042 * in utf8 to call ldap_explode_dn(). JRA. */
3044 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
3047 return WERR_SERVER_UNAVAILABLE;
3049 ads_msgfree(ads, res);
3050 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3052 ldap_memfree(srv_dn_utf8);
3054 return WERR_SERVER_UNAVAILABLE;
3056 /* Now convert to CH_UNIX. */
3057 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3058 ldap_memfree(srv_dn_utf8);
3059 ldap_memfree(srv_cn_utf8);
3061 return WERR_SERVER_UNAVAILABLE;
3063 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3064 ldap_memfree(srv_dn_utf8);
3065 ldap_memfree(srv_cn_utf8);
3068 return WERR_SERVER_UNAVAILABLE;
3071 ldap_memfree(srv_dn_utf8);
3072 ldap_memfree(srv_cn_utf8);
3074 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3075 if (!srv_cn_escaped) {
3076 SAFE_FREE(srv_cn_0);
3077 ldap_memfree(srv_dn_utf8);
3079 return WERR_SERVER_UNAVAILABLE;
3081 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3082 if (!sharename_escaped) {
3083 SAFE_FREE(srv_cn_escaped);
3084 SAFE_FREE(srv_cn_0);
3085 ldap_memfree(srv_dn_utf8);
3087 return WERR_SERVER_UNAVAILABLE;
3091 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3094 SAFE_FREE(srv_cn_0);
3095 SAFE_FREE(srv_cn_escaped);
3096 SAFE_FREE(sharename_escaped);
3098 /* build the ads mods */
3099 ctx = talloc_init("nt_printer_publish_ads");
3105 mods = ads_init_mods(ctx);
3109 talloc_destroy(ctx);
3113 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3114 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3115 printer->info_2->sharename);
3118 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3119 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3120 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3122 if (!ADS_ERR_OK(ads_rc))
3123 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3125 talloc_destroy(ctx);
3127 /* retreive the guid and store it locally */
3128 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3130 ads_pull_guid(ads, res, &guid);
3131 ads_msgfree(ads, res);
3132 store_printer_guid(printer->info_2, guid);
3133 win_rc = mod_a_printer(printer, 2);
3140 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3141 NT_PRINTER_INFO_LEVEL *printer)
3145 char *prt_dn = NULL;
3147 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3149 /* remove the printer from the directory */
3150 ads_rc = ads_find_printer_on_server(ads, &res,
3151 printer->info_2->sharename, global_myname());
3153 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3154 prt_dn = ads_get_dn(ads, res);
3156 ads_msgfree(ads, res);
3159 ads_rc = ads_del_dn(ads, prt_dn);
3160 ads_memfree(ads, prt_dn);
3163 ads_msgfree(ads, res);
3167 /****************************************************************************
3168 * Publish a printer in the directory
3170 * @param snum describing printer service
3171 * @return WERROR indicating status of publishing
3172 ***************************************************************************/
3174 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3177 ADS_STRUCT *ads = NULL;
3178 NT_PRINTER_INFO_LEVEL *printer = NULL;
3181 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3182 if (!W_ERROR_IS_OK(win_rc))
3186 case SPOOL_DS_PUBLISH:
3187 case SPOOL_DS_UPDATE:
3188 /* set the DsSpooler info and attributes */
3189 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3190 win_rc = WERR_NOMEM;
3194 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3196 case SPOOL_DS_UNPUBLISH:
3197 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3200 win_rc = WERR_NOT_SUPPORTED;
3204 win_rc = mod_a_printer(printer, 2);
3205 if (!W_ERROR_IS_OK(win_rc)) {
3206 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3210 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3212 DEBUG(3, ("ads_init() failed\n"));
3213 win_rc = WERR_SERVER_UNAVAILABLE;
3216 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3217 SAFE_FREE(ads->auth.password);
3218 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3221 /* ads_connect() will find the DC for us */
3222 ads_rc = ads_connect(ads);
3223 if (!ADS_ERR_OK(ads_rc)) {
3224 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3225 win_rc = WERR_ACCESS_DENIED;
3230 case SPOOL_DS_PUBLISH:
3231 case SPOOL_DS_UPDATE:
3232 win_rc = nt_printer_publish_ads(ads, printer);
3234 case SPOOL_DS_UNPUBLISH:
3235 win_rc = nt_printer_unpublish_ads(ads, printer);
3240 free_a_printer(&printer, 2);
3245 WERROR check_published_printers(void)
3248 ADS_STRUCT *ads = NULL;
3250 int n_services = lp_numservices();
3251 NT_PRINTER_INFO_LEVEL *printer = NULL;
3253 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3255 DEBUG(3, ("ads_init() failed\n"));
3256 return WERR_SERVER_UNAVAILABLE;
3258 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3259 SAFE_FREE(ads->auth.password);
3260 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3263 /* ads_connect() will find the DC for us */
3264 ads_rc = ads_connect(ads);
3265 if (!ADS_ERR_OK(ads_rc)) {
3266 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3268 ads_kdestroy("MEMORY:prtpub_cache");
3269 return WERR_ACCESS_DENIED;
3272 for (snum = 0; snum < n_services; snum++) {
3273 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3276 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3277 lp_servicename(snum))) &&
3278 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3279 nt_printer_publish_ads(ads, printer);
3281 free_a_printer(&printer, 2);
3285 ads_kdestroy("MEMORY:prtpub_cache");
3289 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3292 NT_PRINTER_INFO_LEVEL *printer = NULL;
3294 REGISTRY_VALUE *guid_val;
3299 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3301 if (!W_ERROR_IS_OK(win_rc) ||
3302 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3303 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3304 !(ctr = printer->info_2->data->keys[i].values) ||
3305 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3307 free_a_printer(&printer, 2);
3311 /* fetching printer guids really ought to be a separate function. */
3316 /* We used to store the guid as REG_BINARY, then swapped
3317 to REG_SZ for Vista compatibility so check for both */
3319 switch ( regval_type(guid_val) ){
3321 rpcstr_pull( guid_str, regval_data_p(guid_val),
3322 sizeof(guid_str)-1, -1, STR_TERMINATE );
3323 ret = smb_string_to_uuid( guid_str, guid );
3326 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3330 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3333 DEBUG(0,("is_printer_published: GUID value stored as "
3334 "invaluid type (%d)\n", regval_type(guid_val) ));
3339 free_a_printer(&printer, 2);
3343 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3348 WERROR check_published_printers(void)
3353 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3358 #endif /* HAVE_ADS */
3360 /****************************************************************************
3361 ***************************************************************************/
3363 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3365 NT_PRINTER_DATA *data;
3367 int removed_keys = 0;
3371 empty_slot = data->num_keys;
3374 return WERR_INVALID_PARAM;
3376 /* remove all keys */
3378 if ( !strlen(key) ) {
3380 TALLOC_FREE( data );
3384 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3390 /* remove a specific key (and all subkeys) */
3392 for ( i=0; i<data->num_keys; i++ ) {
3393 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3394 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3395 data->keys[i].name));
3397 TALLOC_FREE( data->keys[i].name );
3398 TALLOC_FREE( data->keys[i].values );
3400 /* mark the slot as empty */
3402 ZERO_STRUCTP( &data->keys[i] );
3406 /* find the first empty slot */
3408 for ( i=0; i<data->num_keys; i++ ) {
3409 if ( !data->keys[i].name ) {
3416 if ( i == data->num_keys )
3417 /* nothing was removed */
3418 return WERR_INVALID_PARAM;
3420 /* move everything down */
3422 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3423 if ( data->keys[i].name ) {
3424 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3425 ZERO_STRUCTP( &data->keys[i] );
3433 data->num_keys -= removed_keys;
3435 /* sanity check to see if anything is left */
3437 if ( !data->num_keys ) {
3438 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3440 SAFE_FREE( data->keys );
3441 ZERO_STRUCTP( data );
3447 /****************************************************************************
3448 ***************************************************************************/
3450 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3452 WERROR result = WERR_OK;
3455 /* we must have names on non-zero length */
3457 if ( !key || !*key|| !value || !*value )
3458 return WERR_INVALID_NAME;
3460 /* find the printer key first */
3462 key_index = lookup_printerkey( p2->data, key );
3463 if ( key_index == -1 )
3466 /* make sure the value exists so we can return the correct error code */
3468 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3469 return WERR_BADFILE;
3471 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3473 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3479 /****************************************************************************
3480 ***************************************************************************/
3482 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3483 uint32 type, uint8 *data, int real_len )
3485 WERROR result = WERR_OK;
3488 /* we must have names on non-zero length */
3490 if ( !key || !*key|| !value || !*value )
3491 return WERR_INVALID_NAME;
3493 /* find the printer key first */
3495 key_index = lookup_printerkey( p2->data, key );
3496 if ( key_index == -1 )
3497 key_index = add_new_printer_key( p2->data, key );
3499 if ( key_index == -1 )
3502 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3503 type, (const char *)data, real_len );
3505 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3506 key, value, type, real_len ));
3511 /****************************************************************************
3512 ***************************************************************************/
3514 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3518 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3521 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3524 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3527 /****************************************************************************
3528 Unpack a list of registry values frem the TDB
3529 ***************************************************************************/
3531 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3535 pstring string, valuename, keyname;
3539 REGISTRY_VALUE *regval_p;
3542 /* add the "PrinterDriverData" key first for performance reasons */
3544 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3546 /* loop and unpack the rest of the registry values */
3550 /* check to see if there are any more registry values */
3553 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3557 /* unpack the next regval */
3559 len += tdb_unpack(buf+len, buflen-len, "fdB",
3565 /* lookup for subkey names which have a type of REG_NONE */
3566 /* there's no data with this entry */
3568 if ( type == REG_NONE ) {
3569 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3570 add_new_printer_key( printer_data, string );
3575 * break of the keyname from the value name.
3576 * Valuenames can have embedded '\'s so be careful.
3577 * only support one level of keys. See the
3578 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3582 str = strchr_m( string, '\\');
3584 /* Put in "PrinterDriverData" is no key specified */
3587 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3588 pstrcpy( valuename, string );
3592 pstrcpy( keyname, string );
3593 pstrcpy( valuename, str+1 );
3596 /* see if we need a new key */
3598 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3599 key_index = add_new_printer_key( printer_data, keyname );
3601 if ( key_index == -1 ) {
3602 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3607 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3609 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3610 Thanks to Martin Zielinski for the hint. */
3612 if ( type == REG_BINARY &&
3613 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3614 strequal( valuename, "objectGUID" ) )
3617 UNISTR2 unistr_guid;
3619 ZERO_STRUCT( unistr_guid );
3621 /* convert the GUID to a UNICODE string */
3623 memcpy( &guid, data_p, sizeof(struct GUID) );
3625 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3626 UNI_STR_TERMINATE );
3628 regval_ctr_addvalue( printer_data->keys[key_index].values,
3630 (const char *)unistr_guid.buffer,
3631 unistr_guid.uni_str_len*2 );
3636 regval_ctr_addvalue( printer_data->keys[key_index].values,
3637 valuename, type, (const char *)data_p,
3642 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3649 /****************************************************************************
3650 ***************************************************************************/
3652 static void map_to_os2_driver(fstring drivername)
3654 static BOOL initialised=False;
3655 static fstring last_from,last_to;
3656 char *mapfile = lp_os2_driver_map();
3657 char **lines = NULL;
3661 if (!strlen(drivername))
3668 *last_from = *last_to = 0;
3672 if (strequal(drivername,last_from)) {
3673 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3674 fstrcpy(drivername,last_to);
3678 lines = file_lines_load(mapfile, &numlines,0);
3679 if (numlines == 0 || lines == NULL) {
3680 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3685 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3687 for( i = 0; i < numlines; i++) {
3688 char *nt_name = lines[i];
3689 char *os2_name = strchr(nt_name,'=');
3696 while (isspace(*nt_name))
3699 if (!*nt_name || strchr("#;",*nt_name))
3703 int l = strlen(nt_name);
3704 while (l && isspace(nt_name[l-1])) {
3710 while (isspace(*os2_name))
3714 int l = strlen(os2_name);
3715 while (l && isspace(os2_name[l-1])) {
3721 if (strequal(nt_name,drivername)) {
3722 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3723 fstrcpy(last_from,drivername);
3724 fstrcpy(last_to,os2_name);
3725 fstrcpy(drivername,os2_name);
3726 file_lines_free(lines);
3731 file_lines_free(lines);
3734 /****************************************************************************
3735 Get a default printer info 2 struct.
3736 ****************************************************************************/
3737 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3739 int snum = lp_servicenumber(sharename);
3741 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3742 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3743 servername, sharename);
3744 fstrcpy(info->sharename, sharename);
3745 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3747 /* by setting the driver name to an empty string, a local NT admin
3748 can now run the **local** APW to install a local printer driver
3749 for a Samba shared printer in 2.2. Without this, drivers **must** be
3750 installed on the Samba server for NT clients --jerry */
3751 #if 0 /* JERRY --do not uncomment-- */
3752 if (!*info->drivername)
3753 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3757 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3759 pstrcpy(info->comment, "");
3760 fstrcpy(info->printprocessor, "winprint");
3761 fstrcpy(info->datatype, "RAW");
3764 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3765 /* Pull the location and comment strings from cups if we don't
3767 if ( !strlen(info->location) || !strlen(info->comment) )
3768 cups_pull_comment_location( info );
3772 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3774 info->starttime = 0; /* Minutes since 12:00am GMT */
3775 info->untiltime = 0; /* Minutes since 12:00am GMT */
3777 info->default_priority = 1;
3778 info->setuptime = (uint32)time(NULL);
3781 * I changed this as I think it is better to have a generic
3782 * DEVMODE than to crash Win2k explorer.exe --jerry
3783 * See the HP Deskjet 990c Win2k drivers for an example.
3785 * However the default devmode appears to cause problems
3786 * with the HP CLJ 8500 PCL driver. Hence the addition of
3787 * the "default devmode" parameter --jerry 22/01/2002
3790 if (lp_default_devmode(snum)) {
3791 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3795 info->devmode = NULL;
3798 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3806 free_nt_devicemode(&info->devmode);
3808 return WERR_ACCESS_DENIED;
3811 /****************************************************************************
3812 ****************************************************************************/
3813 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3816 int snum = lp_servicenumber(sharename);
3817 TDB_DATA kbuf, dbuf;
3818 fstring printername;
3819 char adevice[MAXDEVICENAME];
3821 kbuf = make_printer_tdbkey( sharename );
3823 dbuf = tdb_fetch(tdb_printers, kbuf);
3825 return get_a_printer_2_default(info, servername, sharename);
3828 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3831 &info->default_priority,
3838 &info->c_setprinter,
3848 info->printprocessor,
3852 /* Samba has to have shared raw drivers. */
3853 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3854 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3856 /* Restore the stripped strings. */
3857 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3859 if ( lp_force_printername(snum) ) {
3860 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3862 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3865 fstrcpy(info->printername, printername);
3868 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3869 /* Pull the location and comment strings from cups if we don't
3871 if ( !strlen(info->location) || !strlen(info->comment) )
3872 cups_pull_comment_location( info );
3876 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3879 * Some client drivers freak out if there is a NULL devmode
3880 * (probably the driver is not checking before accessing
3881 * the devmode pointer) --jerry
3883 * See comments in get_a_printer_2_default()
3886 if (lp_default_devmode(snum) && !info->devmode) {
3887 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3889 info->devmode = construct_nt_devicemode(printername);
3892 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3893 if (info->devmode) {
3894 fstrcpy(info->devmode->devicename, adevice);
3897 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3898 DEBUG(0,("unpack_values: talloc() failed!\n"));
3899 SAFE_FREE(dbuf.dptr);
3902 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3904 /* This will get the current RPC talloc context, but we should be
3905 passing this as a parameter... fixme... JRA ! */
3907 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3908 SAFE_FREE(dbuf.dptr);
3912 /* Fix for OS/2 drivers. */
3914 if (get_remote_arch() == RA_OS2) {
3915 map_to_os2_driver(info->drivername);
3918 SAFE_FREE(dbuf.dptr);
3920 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3921 sharename, info->printername, info->drivername));
3926 /****************************************************************************
3927 Debugging function, dump at level 6 the struct in the logs.
3928 ****************************************************************************/
3929 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3932 NT_PRINTER_INFO_LEVEL_2 *info2;
3934 DEBUG(106,("Dumping printer at level [%d]\n", level));
3939 if (printer->info_2 == NULL)
3943 info2=printer->info_2;
3945 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3946 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3947 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3948 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3949 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3950 DEBUGADD(106,("status:[%d]\n", info2->status));
3951 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3952 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3953 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3954 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3955 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3957 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3958 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3959 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3960 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3961 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3962 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3963 DEBUGADD(106,("location:[%s]\n", info2->location));
3964 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3965 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3966 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3967 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3973 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3981 /****************************************************************************
3982 Update the changeid time.
3983 This is SO NASTY as some drivers need this to change, others need it
3984 static. This value will change every second, and I must hope that this
3985 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3987 ****************************************************************************/
3989 static uint32 rev_changeid(void)
3993 get_process_uptime(&tv);
3996 /* Return changeid as msec since spooler restart */
3997 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4000 * This setting seems to work well but is too untested
4001 * to replace the above calculation. Left in for experiementation
4002 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4004 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4010 * The function below are the high level ones.
4011 * only those ones must be called from the spoolss code.
4015 /****************************************************************************
4016 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4017 ****************************************************************************/
4019 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4023 dump_a_printer(printer, level);
4029 * Update the changestamp. Emperical tests show that the
4030 * ChangeID is always updated,but c_setprinter is
4031 * global spooler variable (not per printer).
4034 /* ChangeID **must** be increasing over the lifetime
4035 of client's spoolss service in order for the
4036 client's cache to show updates */
4038 printer->info_2->changeid = rev_changeid();
4041 * Because one day someone will ask:
4042 * NT->NT An admin connection to a remote
4043 * printer show changes imeediately in
4044 * the properities dialog
4046 * A non-admin connection will only show the
4047 * changes after viewing the properites page
4048 * 2 times. Seems to be related to a
4049 * race condition in the client between the spooler
4050 * updating the local cache and the Explorer.exe GUI
4051 * actually displaying the properties.
4053 * This is fixed in Win2k. admin/non-admin
4054 * connections both display changes immediately.
4059 result=update_a_printer_2(printer->info_2);
4064 result=WERR_UNKNOWN_LEVEL;
4071 /****************************************************************************
4072 Initialize printer devmode & data with previously saved driver init values.
4073 ****************************************************************************/
4075 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4080 NT_PRINTER_INFO_LEVEL_2 info;
4086 * Delete any printer data 'values' already set. When called for driver
4087 * replace, there will generally be some, but during an add printer, there
4088 * should not be any (if there are delete them).
4091 if ( info_ptr->data )
4092 delete_all_printer_data( info_ptr, "" );
4094 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4096 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4099 * When changing to a driver that has no init info in the tdb, remove
4100 * the previous drivers init info and leave the new on blank.
4102 free_nt_devicemode(&info_ptr->devmode);
4107 * Get the saved DEVMODE..
4110 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4113 * The saved DEVMODE contains the devicename from the printer used during
4114 * the initialization save. Change it to reflect the new printer.
4117 if ( info.devmode ) {
4118 ZERO_STRUCT(info.devmode->devicename);
4119 fstrcpy(info.devmode->devicename, info_ptr->printername);
4123 * NT/2k does not change out the entire DeviceMode of a printer
4124 * when changing the driver. Only the driverextra, private, &
4125 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4127 * Later examination revealed that Windows NT/2k does reset the
4128 * the printer's device mode, bit **only** when you change a
4129 * property of the device mode such as the page orientation.
4134 /* Bind the saved DEVMODE to the new the printer */
4136 free_nt_devicemode(&info_ptr->devmode);
4137 info_ptr->devmode = info.devmode;
4139 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4140 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4142 /* Add the printer data 'values' to the new printer */
4144 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4145 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4149 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4152 SAFE_FREE(dbuf.dptr);
4157 /****************************************************************************
4158 Initialize printer devmode & data with previously saved driver init values.
4159 When a printer is created using AddPrinter, the drivername bound to the
4160 printer is used to lookup previously saved driver initialization info, which
4161 is bound to the new printer.
4162 ****************************************************************************/
4164 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4166 BOOL result = False;
4170 result = set_driver_init_2(printer->info_2);
4174 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4182 /****************************************************************************
4183 Delete driver init data stored for a specified driver
4184 ****************************************************************************/
4186 BOOL del_driver_init(char *drivername)
4190 if (!drivername || !*drivername) {
4191 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4195 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4197 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4199 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4202 /****************************************************************************
4203 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4204 in the tdb. Note: this is different from the driver entry and the printer
4205 entry. There should be a single driver init entry for each driver regardless
4206 of whether it was installed from NT or 2K. Technically, they should be
4207 different, but they work out to the same struct.
4208 ****************************************************************************/
4210 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4214 int buflen, len, ret;
4222 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4224 len += pack_values( info->data, buf+len, buflen-len );
4227 buf = (uint8 *)SMB_REALLOC(buf, len);
4229 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4237 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4242 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4246 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4250 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4251 info->sharename, info->drivername));
4256 /****************************************************************************
4257 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4258 ****************************************************************************/
4260 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4264 dump_a_printer(printer, level);
4268 result = update_driver_init_2(printer->info_2);
4278 /****************************************************************************
4279 Convert the printer data value, a REG_BINARY array, into an initialization
4280 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4281 got to keep the endians happy :).
4282 ****************************************************************************/
4284 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4286 BOOL result = False;
4290 ZERO_STRUCT(devmode);
4292 prs_init(&ps, 0, ctx, UNMARSHALL);
4293 ps.data_p = (char *)data;
4294 ps.buffer_size = data_len;
4296 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4297 result = convert_devicemode("", &devmode, &nt_devmode);
4299 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4304 /****************************************************************************
4305 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4307 1. Use the driver's config DLL to this UNC printername and:
4308 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4309 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4310 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4312 The last step triggers saving the "driver initialization" information for
4313 this printer into the tdb. Later, new printers that use this driver will
4314 have this initialization information bound to them. This simulates the
4315 driver initialization, as if it had run on the Samba server (as it would
4318 The Win32 client side code requirement sucks! But until we can run arbitrary
4319 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4321 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4322 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4323 about it and you will realize why. JRR 010720
4324 ****************************************************************************/
4326 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4328 WERROR status = WERR_OK;
4329 TALLOC_CTX *ctx = NULL;
4330 NT_DEVICEMODE *nt_devmode = NULL;
4331 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4334 * When the DEVMODE is already set on the printer, don't try to unpack it.
4336 DEBUG(8,("save_driver_init_2: Enter...\n"));
4338 if ( !printer->info_2->devmode && data_len ) {
4340 * Set devmode on printer info, so entire printer initialization can be
4344 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4347 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4348 status = WERR_NOMEM;
4352 ZERO_STRUCTP(nt_devmode);
4355 * The DEVMODE is held in the 'data' component of the param in raw binary.
4356 * Convert it to to a devmode structure
4358 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4359 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4360 status = WERR_INVALID_PARAM;
4364 printer->info_2->devmode = nt_devmode;
4368 * Pack up and add (or update) the DEVMODE and any current printer data to
4369 * a 'driver init' element in the tdb
4373 if ( update_driver_init(printer, 2) != 0 ) {
4374 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4375 status = WERR_NOMEM;
4380 * If driver initialization info was successfully saved, set the current
4381 * printer to match it. This allows initialization of the current printer
4382 * as well as the driver.
4384 status = mod_a_printer(printer, 2);
4385 if (!W_ERROR_IS_OK(status)) {
4386 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4387 printer->info_2->printername));
4391 talloc_destroy(ctx);
4392 free_nt_devicemode( &nt_devmode );
4394 printer->info_2->devmode = tmp_devmode;
4399 /****************************************************************************
4400 Update the driver init info (DEVMODE and specifics) for a printer
4401 ****************************************************************************/
4403 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4405 WERROR status = WERR_OK;
4409 status = save_driver_init_2( printer, data, data_len );
4412 status = WERR_UNKNOWN_LEVEL;
4419 /****************************************************************************
4420 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4422 Previously the code had a memory allocation problem because it always
4423 used the TALLOC_CTX from the Printer_entry*. This context lasts
4424 as a long as the original handle is open. So if the client made a lot
4425 of getprinter[data]() calls, the memory usage would climb. Now we use
4426 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4427 still use the Printer_entry->ctx for maintaining the cache copy though
4428 since that object must live as long as the handle by definition.
4431 ****************************************************************************/
4433 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4434 const char *sharename)
4439 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4441 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4442 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4448 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4449 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4450 TALLOC_FREE( *pp_printer );
4455 fstrcpy( servername, print_hnd->servername );
4457 fstrcpy( servername, "%L" );
4458 standard_sub_basic( "", "", servername,
4459 sizeof(servername)-1 );
4462 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4465 /* we have a new printer now. Save it with this handle */
4467 if ( !W_ERROR_IS_OK(result) ) {
4468 TALLOC_FREE( *pp_printer );
4469 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4470 sharename, (unsigned int)level, dos_errstr(result)));
4474 dump_a_printer( *pp_printer, level);
4479 TALLOC_FREE( *pp_printer );
4480 return WERR_UNKNOWN_LEVEL;
4486 /****************************************************************************
4487 Deletes a NT_PRINTER_INFO_LEVEL struct.
4488 ****************************************************************************/
4490 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4492 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4499 if ( printer->info_2 )
4500 free_nt_printer_info_level_2(&printer->info_2);
4504 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4508 TALLOC_FREE(*pp_printer);
4513 /****************************************************************************
4514 ****************************************************************************/
4515 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4518 DEBUG(104,("adding a printer at level [%d]\n", level));
4519 dump_a_printer_driver(driver, level);
4523 result=add_a_printer_driver_3(driver.info_3);
4527 result=add_a_printer_driver_6(driver.info_6);
4537 /****************************************************************************
4538 ****************************************************************************/
4540 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4541 fstring drivername, const char *architecture, uint32 version)
4547 /* Sometime we just want any version of the driver */
4549 if ( version == DRIVER_ANY_VERSION ) {
4550 /* look for Win2k first and then for NT4 */
4551 result = get_a_printer_driver_3(&driver->info_3, drivername,
4554 if ( !W_ERROR_IS_OK(result) ) {
4555 result = get_a_printer_driver_3( &driver->info_3,
4556 drivername, architecture, 2 );
4559 result = get_a_printer_driver_3(&driver->info_3, drivername,
4560 architecture, version);
4569 if (W_ERROR_IS_OK(result))
4570 dump_a_printer_driver(*driver, level);
4575 /****************************************************************************
4576 ****************************************************************************/
4577 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4584 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4585 if (driver.info_3 != NULL)
4587 info3=driver.info_3;
4588 SAFE_FREE(info3->dependentfiles);
4589 ZERO_STRUCTP(info3);
4599 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4600 if (driver.info_6 != NULL) {
4601 info6=driver.info_6;
4602 SAFE_FREE(info6->dependentfiles);
4603 SAFE_FREE(info6->previousnames);
4604 ZERO_STRUCTP(info6);
4620 /****************************************************************************
4621 Determine whether or not a particular driver is currently assigned
4623 ****************************************************************************/
4625 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4628 int n_services = lp_numservices();
4629 NT_PRINTER_INFO_LEVEL *printer = NULL;
4630 BOOL in_use = False;
4635 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4637 /* loop through the printers.tdb and check for the drivername */
4639 for (snum=0; snum<n_services && !in_use; snum++) {
4640 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4643 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4646 if ( strequal(info_3->name, printer->info_2->drivername) )
4649 free_a_printer( &printer, 2 );
4652 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4655 NT_PRINTER_DRIVER_INFO_LEVEL d;
4658 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4660 /* we can still remove the driver if there is one of
4661 "Windows NT x86" version 2 or 3 left */
4663 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4664 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4667 switch ( info_3->cversion ) {
4669 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4672 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4675 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4677 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4682 /* now check the error code */
4684 if ( W_ERROR_IS_OK(werr) ) {
4685 /* it's ok to remove the driver, we have other architctures left */
4687 free_a_printer_driver( d, 3 );
4691 /* report that the driver is not in use by default */
4697 /**********************************************************************
4698 Check to see if a ogiven file is in use by *info
4699 *********************************************************************/
4701 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4708 if ( strequal(file, info->driverpath) )
4711 if ( strequal(file, info->datafile) )
4714 if ( strequal(file, info->configfile) )
4717 if ( strequal(file, info->helpfile) )
4720 /* see of there are any dependent files to examine */
4722 if ( !info->dependentfiles )
4725 while ( *info->dependentfiles[i] ) {
4726 if ( strequal(file, info->dependentfiles[i]) )
4735 /**********************************************************************
4736 Utility function to remove the dependent file pointed to by the
4737 input parameter from the list
4738 *********************************************************************/
4740 static void trim_dependent_file( fstring files[], int idx )
4743 /* bump everything down a slot */
4745 while( *files[idx+1] ) {
4746 fstrcpy( files[idx], files[idx+1] );
4755 /**********************************************************************
4756 Check if any of the files used by src are also used by drv
4757 *********************************************************************/
4759 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4760 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4762 BOOL in_use = False;
4768 /* check each file. Remove it from the src structure if it overlaps */
4770 if ( drv_file_in_use(src->driverpath, drv) ) {
4772 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4773 fstrcpy( src->driverpath, "" );
4776 if ( drv_file_in_use(src->datafile, drv) ) {
4778 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4779 fstrcpy( src->datafile, "" );
4782 if ( drv_file_in_use(src->configfile, drv) ) {
4784 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4785 fstrcpy( src->configfile, "" );
4788 if ( drv_file_in_use(src->helpfile, drv) ) {
4790 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4791 fstrcpy( src->helpfile, "" );
4794 /* are there any dependentfiles to examine? */
4796 if ( !src->dependentfiles )
4799 while ( *src->dependentfiles[i] ) {
4800 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4802 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4803 trim_dependent_file( src->dependentfiles, i );
4811 /****************************************************************************
4812 Determine whether or not a particular driver files are currently being
4813 used by any other driver.
4815 Return value is True if any files were in use by other drivers
4816 and False otherwise.
4818 Upon return, *info has been modified to only contain the driver files
4819 which are not in use
4820 ****************************************************************************/
4822 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4827 fstring *list = NULL;
4828 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4833 version = info->cversion;
4835 /* loop over all driver versions */
4837 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4839 /* get the list of drivers */
4842 ndrivers = get_ntdrivers(&list, info->environment, version);
4844 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4845 ndrivers, info->environment, version));
4847 /* check each driver for overlap in files */
4849 for (i=0; i<ndrivers; i++) {
4850 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4852 ZERO_STRUCT(driver);
4854 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4859 /* check if d2 uses any files from d1 */
4860 /* only if this is a different driver than the one being deleted */
4862 if ( !strequal(info->name, driver.info_3->name) ) {
4863 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4864 free_a_printer_driver(driver, 3);
4870 free_a_printer_driver(driver, 3);
4875 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4877 driver.info_3 = info;
4879 if ( DEBUGLEVEL >= 20 )
4880 dump_a_printer_driver( driver, 3 );
4885 /****************************************************************************
4886 Actually delete the driver files. Make sure that
4887 printer_driver_files_in_use() return False before calling
4889 ****************************************************************************/
4891 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4896 connection_struct *conn;
4905 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4908 * Connect to the print$ share under the same account as the
4909 * user connected to the rpc pipe. Note we must be root to
4913 null_pw = data_blob_null;
4914 fstrcpy(res_type, "A:");
4916 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4920 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4924 if ( !CAN_WRITE(conn) ) {
4925 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4929 /* Save who we are - we are temporarily becoming the connection user. */
4931 if ( !become_user(conn, conn->vuid) ) {
4932 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4936 /* now delete the files; must strip the '\print$' string from
4939 if ( *info_3->driverpath ) {
4940 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4942 driver_unix_convert(file, conn, NULL, &st);
4943 DEBUG(10,("deleting driverfile [%s]\n", s));
4944 unlink_internals(conn, 0, file, False, False);
4948 if ( *info_3->configfile ) {
4949 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4951 driver_unix_convert(file, conn, NULL, &st);
4952 DEBUG(10,("deleting configfile [%s]\n", s));
4953 unlink_internals(conn, 0, file, False, False);
4957 if ( *info_3->datafile ) {
4958 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4960 driver_unix_convert(file, conn, NULL, &st);
4961 DEBUG(10,("deleting datafile [%s]\n", s));
4962 unlink_internals(conn, 0, file, False, False);
4966 if ( *info_3->helpfile ) {
4967 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4969 driver_unix_convert(file, conn, NULL, &st);
4970 DEBUG(10,("deleting helpfile [%s]\n", s));
4971 unlink_internals(conn, 0, file, False, False);
4975 /* check if we are done removing files */
4977 if ( info_3->dependentfiles ) {
4978 while ( info_3->dependentfiles[i][0] ) {
4981 /* bypass the "\print$" portion of the path */
4983 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4985 driver_unix_convert(file, conn, NULL, &st);
4986 DEBUG(10,("deleting dependent file [%s]\n", file));
4987 unlink_internals(conn, 0, file, False, False);
4999 /****************************************************************************
5000 Remove a printer driver from the TDB. This assumes that the the driver was
5001 previously looked up.
5002 ***************************************************************************/
5004 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5005 uint32 version, BOOL delete_files )
5010 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5012 /* delete the tdb data first */
5014 arch = get_short_archi(info_3->environment);
5016 return WERR_UNKNOWN_PRINTER_DRIVER;
5018 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5019 arch, version, info_3->name);
5021 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5022 key, delete_files ? "TRUE" : "FALSE" ));
5024 ctr.info_3 = info_3;
5025 dump_a_printer_driver( ctr, 3 );
5027 /* check if the driver actually exists for this environment */
5029 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5031 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5032 return WERR_UNKNOWN_PRINTER_DRIVER;
5035 SAFE_FREE( dbuf.dptr );
5037 /* ok... the driver exists so the delete should return success */
5039 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5040 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5041 return WERR_ACCESS_DENIED;
5045 * now delete any associated files if delete_files == True
5046 * even if this part failes, we return succes because the
5047 * driver doesn not exist any more
5051 delete_driver_files( info_3, user );
5054 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5059 /****************************************************************************
5060 Store a security desc for a printer.
5061 ****************************************************************************/
5063 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5065 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5066 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5068 TALLOC_CTX *mem_ctx = NULL;
5072 mem_ctx = talloc_init("nt_printing_setsec");
5073 if (mem_ctx == NULL)
5076 /* The old owner and group sids of the security descriptor are not
5077 present when new ACEs are added or removed by changing printer
5078 permissions through NT. If they are NULL in the new security
5079 descriptor then copy them over from the old one. */
5081 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5082 DOM_SID *owner_sid, *group_sid;
5083 SEC_ACL *dacl, *sacl;
5084 SEC_DESC *psd = NULL;
5087 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5088 status = WERR_NOMEM;
5092 /* Pick out correct owner and group sids */
5094 owner_sid = secdesc_ctr->sd->owner_sid ?
5095 secdesc_ctr->sd->owner_sid :
5096 old_secdesc_ctr->sd->owner_sid;
5098 group_sid = secdesc_ctr->sd->group_sid ?
5099 secdesc_ctr->sd->group_sid :
5100 old_secdesc_ctr->sd->group_sid;
5102 dacl = secdesc_ctr->sd->dacl ?
5103 secdesc_ctr->sd->dacl :
5104 old_secdesc_ctr->sd->dacl;
5106 sacl = secdesc_ctr->sd->sacl ?
5107 secdesc_ctr->sd->sacl :
5108 old_secdesc_ctr->sd->sacl;
5110 /* Make a deep copy of the security descriptor */
5112 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5113 owner_sid, group_sid,
5119 status = WERR_NOMEM;
5123 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5126 if (!new_secdesc_ctr) {
5127 new_secdesc_ctr = secdesc_ctr;
5130 /* Store the security descriptor in a tdb */
5132 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5133 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5135 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5137 status = WERR_BADFUNC;
5141 kbuf = make_printers_secdesc_tdbkey( sharename );
5143 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5146 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5147 status = WERR_BADFUNC;
5150 /* Free malloc'ed memory */
5156 talloc_destroy(mem_ctx);
5160 /****************************************************************************
5161 Construct a default security descriptor buffer for a printer.
5162 ****************************************************************************/
5164 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5166 SEC_ACE ace[5]; /* max number of ace entries */
5169 SEC_ACL *psa = NULL;
5170 SEC_DESC_BUF *sdb = NULL;
5171 SEC_DESC *psd = NULL;
5175 /* Create an ACE where Everyone is allowed to print */
5177 init_sec_access(&sa, PRINTER_ACE_PRINT);
5178 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5179 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5181 /* Add the domain admins group if we are a DC */
5184 DOM_SID domadmins_sid;
5186 sid_copy(&domadmins_sid, get_global_sam_sid());
5187 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5189 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5190 init_sec_ace(&ace[i++], &domadmins_sid,
5191 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5192 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5193 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5194 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5196 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5197 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5199 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5200 init_sec_ace(&ace[i++], &adm_sid,
5201 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5202 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5203 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5204 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5207 /* add BUILTIN\Administrators as FULL CONTROL */
5209 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5210 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5211 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5212 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5213 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5214 SEC_ACE_TYPE_ACCESS_ALLOWED,
5215 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5217 /* Make the security descriptor owned by the BUILTIN\Administrators */
5219 /* The ACL revision number in rpc_secdesc.h differs from the one
5220 created by NT when setting ACE entries in printer
5221 descriptors. NT4 complains about the property being edited by a
5224 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5225 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5226 &global_sid_Builtin_Administrators,
5227 &global_sid_Builtin_Administrators,
5228 NULL, psa, &sd_size);
5232 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5236 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5238 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5239 (unsigned int)sd_size));
5244 /****************************************************************************
5245 Get a security desc for a printer.
5246 ****************************************************************************/
5248 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5254 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5255 sharename = temp + 1;
5260 /* Fetch security descriptor from tdb */
5262 kbuf = make_printers_secdesc_tdbkey( sharename );
5264 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5265 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5269 DEBUG(4,("using default secdesc for %s\n", sharename));
5271 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5275 /* Save default security descriptor for later */
5277 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5278 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5280 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5281 tdb_prs_store(tdb_printers, kbuf, &ps);
5291 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5292 this security descriptor has been created when winbindd was
5293 down. Take ownership of security descriptor. */
5295 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5298 /* Change sd owner to workgroup administrator */
5300 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5301 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5302 SEC_DESC *psd = NULL;
5307 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5309 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5311 (*secdesc_ctr)->sd->group_sid,
5312 (*secdesc_ctr)->sd->sacl,
5313 (*secdesc_ctr)->sd->dacl,
5320 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5321 if (!new_secdesc_ctr) {
5325 /* Swap with other one */
5327 *secdesc_ctr = new_secdesc_ctr;
5331 nt_printing_setsec(sharename, *secdesc_ctr);
5335 if (DEBUGLEVEL >= 10) {
5336 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5339 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5340 sharename, the_acl->num_aces));
5342 for (i = 0; i < the_acl->num_aces; i++) {
5345 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5347 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5348 the_acl->aces[i].type, the_acl->aces[i].flags,
5349 the_acl->aces[i].access_mask));
5358 1: level not implemented
5359 2: file doesn't exist
5360 3: can't allocate memory
5361 4: can't free memory
5362 5: non existant struct
5366 A printer and a printer driver are 2 different things.
5367 NT manages them separatelly, Samba does the same.
5368 Why ? Simply because it's easier and it makes sense !
5370 Now explanation: You have 3 printers behind your samba server,
5371 2 of them are the same make and model (laser A and B). But laser B
5372 has an 3000 sheet feeder and laser A doesn't such an option.
5373 Your third printer is an old dot-matrix model for the accounting :-).
5375 If the /usr/local/samba/lib directory (default dir), you will have
5376 5 files to describe all of this.
5378 3 files for the printers (1 by printer):
5381 NTprinter_accounting
5382 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5383 NTdriver_printer model X
5384 NTdriver_printer model Y
5386 jfm: I should use this comment for the text file to explain
5387 same thing for the forms BTW.
5388 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5392 /* Convert generic access rights to printer object specific access rights.
5393 It turns out that NT4 security descriptors use generic access rights and
5394 NT5 the object specific ones. */
5396 void map_printer_permissions(SEC_DESC *sd)
5400 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5401 se_map_generic(&sd->dacl->aces[i].access_mask,
5402 &printer_generic_mapping);
5406 /****************************************************************************
5407 Check a user has permissions to perform the given operation. We use the
5408 permission constants defined in include/rpc_spoolss.h to check the various
5409 actions we perform when checking printer access.
5411 PRINTER_ACCESS_ADMINISTER:
5412 print_queue_pause, print_queue_resume, update_printer_sec,
5413 update_printer, spoolss_addprinterex_level_2,
5414 _spoolss_setprinterdata
5419 JOB_ACCESS_ADMINISTER:
5420 print_job_delete, print_job_pause, print_job_resume,
5423 Try access control in the following order (for performance reasons):
5424 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5425 2) check security descriptor (bit comparisons in memory)
5426 3) "printer admins" (may result in numerous calls to winbind)
5428 ****************************************************************************/
5429 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5431 SEC_DESC_BUF *secdesc = NULL;
5432 uint32 access_granted;
5436 TALLOC_CTX *mem_ctx = NULL;
5437 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5439 /* If user is NULL then use the current_user structure */
5442 user = ¤t_user;
5444 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5446 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5450 /* Get printer name */
5452 pname = PRINTERNAME(snum);
5454 if (!pname || !*pname) {
5459 /* Get printer security descriptor */
5461 if(!(mem_ctx = talloc_init("print_access_check"))) {
5466 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5467 talloc_destroy(mem_ctx);
5472 if (access_type == JOB_ACCESS_ADMINISTER) {
5473 SEC_DESC_BUF *parent_secdesc = secdesc;
5475 /* Create a child security descriptor to check permissions
5476 against. This is because print jobs are child objects
5477 objects of a printer. */
5479 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5482 talloc_destroy(mem_ctx);
5487 /* Now this is the bit that really confuses me. The access
5488 type needs to be changed from JOB_ACCESS_ADMINISTER to
5489 PRINTER_ACCESS_ADMINISTER for this to work. Something
5490 to do with the child (job) object becoming like a
5493 access_type = PRINTER_ACCESS_ADMINISTER;
5498 map_printer_permissions(secdesc->sd);
5500 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5501 &access_granted, &status);
5503 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5505 /* see if we need to try the printer admin list */
5507 if ((access_granted == 0) &&
5508 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5509 user->nt_user_token,
5510 lp_printer_admin(snum)))) {
5511 talloc_destroy(mem_ctx);
5515 talloc_destroy(mem_ctx);
5524 /****************************************************************************
5525 Check the time parameters allow a print operation.
5526 *****************************************************************************/
5528 BOOL print_time_access_check(const char *servicename)
5530 NT_PRINTER_INFO_LEVEL *printer = NULL;
5532 time_t now = time(NULL);
5536 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5539 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5543 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5545 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5548 free_a_printer(&printer, 2);
5556 /****************************************************************************
5557 Fill in the servername sent in the _spoolss_open_printer_ex() call
5558 ****************************************************************************/
5560 char* get_server_name( Printer_entry *printer )
5562 return printer->servername;