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 );
244 key.dsize = strlen(keystr)+1;
249 /****************************************************************************
250 generate a new TDB_DATA key for storing a printer security descriptor
251 ****************************************************************************/
253 static char *make_printers_secdesc_tdbkey( const char* sharename )
256 static pstring keystr;
258 fstrcpy( share, sharename );
261 pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
266 /****************************************************************************
267 ****************************************************************************/
269 static BOOL upgrade_to_version_3(void)
271 TDB_DATA kbuf, newkey, dbuf;
273 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
275 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
276 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
278 dbuf = tdb_fetch(tdb_drivers, kbuf);
280 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
281 DEBUG(0,("upgrade_to_version_3:moving form\n"));
282 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
287 if (tdb_delete(tdb_drivers, kbuf) != 0) {
288 SAFE_FREE(dbuf.dptr);
289 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
294 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
295 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
301 if (tdb_delete(tdb_drivers, kbuf) != 0) {
302 SAFE_FREE(dbuf.dptr);
303 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
308 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
309 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
315 if (tdb_delete(tdb_drivers, kbuf) != 0) {
316 SAFE_FREE(dbuf.dptr);
317 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
322 SAFE_FREE(dbuf.dptr);
328 /*******************************************************************
329 Fix an issue with security descriptors. Printer sec_desc must
330 use more than the generic bits that were previously used
331 in <= 3.0.14a. They must also have a owner and group SID assigned.
332 Otherwise, any printers than have been migrated to a Windows
333 host using printmig.exe will not be accessible.
334 *******************************************************************/
336 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
337 TDB_DATA data, void *state )
340 SEC_DESC_BUF *sd_orig = NULL;
341 SEC_DESC_BUF *sd_new, *sd_store;
342 SEC_DESC *sec, *new_sec;
343 TALLOC_CTX *ctx = state;
349 if (!data.dptr || data.dsize == 0) {
353 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
357 /* upgrade the security descriptor */
361 prs_init( &ps, 0, ctx, UNMARSHALL );
362 prs_give_memory( &ps, data.dptr, data.dsize, False );
364 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
365 /* delete bad entries */
366 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
367 tdb_delete( tdb_printers, key );
378 /* is this even valid? */
385 /* update access masks */
387 for ( i=0; i<sec->dacl->num_aces; i++ ) {
388 switch ( sec->dacl->ace[i].info.mask ) {
389 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
390 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
393 case GENERIC_ALL_ACCESS:
394 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
397 case READ_CONTROL_ACCESS:
398 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
400 default: /* no change */
405 /* create a new SEC_DESC with the appropriate owner and group SIDs */
407 string_to_sid(&sid, "S-1-5-32-544" );
408 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
410 NULL, NULL, &size_new_sec );
415 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
421 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
422 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
431 sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
432 prs_init(&ps, sd_size, ctx, MARSHALL);
434 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
435 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
440 data.dptr = prs_data_p( &ps );
441 data.dsize = sd_size;
443 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
447 /* 0 to continue and non-zero to stop traversal */
449 return (result == -1);
452 /*******************************************************************
453 *******************************************************************/
455 static BOOL upgrade_to_version_4(void)
460 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
462 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
465 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
467 talloc_destroy( ctx );
469 return ( result != -1 );
472 /*******************************************************************
473 Fix an issue with security descriptors. Printer sec_desc must
474 use more than the generic bits that were previously used
475 in <= 3.0.14a. They must also have a owner and group SID assigned.
476 Otherwise, any printers than have been migrated to a Windows
477 host using printmig.exe will not be accessible.
478 *******************************************************************/
480 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
481 TDB_DATA data, void *state )
485 if (!data.dptr || data.dsize == 0)
488 /* upgrade printer records and security descriptors */
490 if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
491 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
493 else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
494 new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) );
495 new_key.dsize = strlen( new_key.dptr ) + 1;
498 /* ignore this record */
502 /* delete the original record and store under the normalized key */
504 if ( tdb_delete( the_tdb, key ) != 0 ) {
505 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
510 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
511 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
519 /*******************************************************************
520 *******************************************************************/
522 static BOOL upgrade_to_version_5(void)
527 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
529 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
532 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
534 talloc_destroy( ctx );
536 return ( result != -1 );
539 /****************************************************************************
540 Open the NT printing tdbs. Done once before fork().
541 ****************************************************************************/
543 BOOL nt_printing_init(void)
545 const char *vstring = "INFO/version";
549 if ( tdb_drivers && tdb_printers && tdb_forms )
553 tdb_close(tdb_drivers);
554 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
556 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
557 lock_path("ntdrivers.tdb"), strerror(errno) ));
562 tdb_close(tdb_printers);
563 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
565 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
566 lock_path("ntprinters.tdb"), strerror(errno) ));
571 tdb_close(tdb_forms);
572 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
574 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
575 lock_path("ntforms.tdb"), strerror(errno) ));
579 /* handle a Samba upgrade */
581 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
583 DEBUG(10, ("Fresh database\n"));
584 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
585 vers_id = NTDRIVERS_DATABASE_VERSION_5;
588 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
590 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
591 if (!upgrade_to_version_3())
593 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
594 vers_id = NTDRIVERS_DATABASE_VERSION_3;
597 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
598 /* Written on a bigendian machine with old fetch_int code. Save as le. */
599 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
600 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
601 vers_id = NTDRIVERS_DATABASE_VERSION_3;
604 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
605 if ( !upgrade_to_version_4() )
607 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
608 vers_id = NTDRIVERS_DATABASE_VERSION_4;
611 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
612 if ( !upgrade_to_version_5() )
614 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
615 vers_id = NTDRIVERS_DATABASE_VERSION_5;
619 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
620 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
625 update_c_setprinter(True);
628 * register callback to handle updating printers as new
629 * drivers are installed
632 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
635 * register callback to handle updating printer data
636 * when a driver is initialized
639 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
641 /* of course, none of the message callbacks matter if you don't
642 tell messages.c that you interested in receiving PRINT_GENERAL
643 msgs. This is done in claim_connection() */
646 if ( lp_security() == SEC_ADS ) {
647 win_rc = check_published_printers();
648 if (!W_ERROR_IS_OK(win_rc))
649 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
655 /*******************************************************************
656 Function to allow filename parsing "the old way".
657 ********************************************************************/
659 static BOOL driver_unix_convert(char *name,connection_struct *conn,
660 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
663 unix_clean_name(name);
664 trim_string(name,"/","/");
665 return unix_convert(name, conn, saved_last_component, bad_path, pst);
668 /*******************************************************************
669 tdb traversal function for counting printers.
670 ********************************************************************/
672 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
673 TDB_DATA data, void *context)
675 int *printer_count = (int*)context;
677 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
679 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
685 /*******************************************************************
686 Update the spooler global c_setprinter. This variable is initialized
687 when the parent smbd starts with the number of existing printers. It
688 is monotonically increased by the current number of printers *after*
689 each add or delete printer RPC. Only Microsoft knows why... JRR020119
690 ********************************************************************/
692 uint32 update_c_setprinter(BOOL initialize)
695 int32 printer_count = 0;
697 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
699 /* Traverse the tdb, counting the printers */
700 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
702 /* If initializing, set c_setprinter to current printers count
703 * otherwise, bump it by the current printer count
706 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
708 c_setprinter = printer_count;
710 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
711 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
713 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
715 return (uint32)c_setprinter;
718 /*******************************************************************
719 Get the spooler global c_setprinter, accounting for initialization.
720 ********************************************************************/
722 uint32 get_c_setprinter(void)
724 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
726 if (c_setprinter == (int32)-1)
727 c_setprinter = update_c_setprinter(True);
729 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
731 return (uint32)c_setprinter;
734 /****************************************************************************
735 Get builtin form struct list.
736 ****************************************************************************/
738 int get_builtin_ntforms(nt_forms_struct **list)
740 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
744 return sizeof(default_forms) / sizeof(default_forms[0]);
747 /****************************************************************************
748 get a builtin form struct
749 ****************************************************************************/
751 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
755 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
756 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
757 count = sizeof(default_forms) / sizeof(default_forms[0]);
758 for (i=0;i<count;i++) {
759 if (strequal(form_name,default_forms[i].name)) {
760 DEBUGADD(6,("Found builtin form %s \n", form_name));
761 memcpy(form,&default_forms[i],sizeof(*form));
769 /****************************************************************************
770 get a form struct list.
771 ****************************************************************************/
773 int get_ntforms(nt_forms_struct **list)
775 TDB_DATA kbuf, newkey, dbuf;
776 nt_forms_struct form;
783 for (kbuf = tdb_firstkey(tdb_forms);
785 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
787 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
790 dbuf = tdb_fetch(tdb_forms, kbuf);
794 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
795 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
796 &i, &form.flag, &form.width, &form.length, &form.left,
797 &form.top, &form.right, &form.bottom);
798 SAFE_FREE(dbuf.dptr);
799 if (ret != dbuf.dsize)
802 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
804 DEBUG(0,("get_ntforms: Realloc fail.\n"));
815 /****************************************************************************
816 write a form struct list
817 ****************************************************************************/
818 int write_ntforms(nt_forms_struct **list, int number)
825 for (i=0;i<number;i++) {
826 /* save index, so list is rebuilt in correct order */
827 len = tdb_pack(buf, sizeof(buf), "dddddddd",
828 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
829 (*list)[i].left, (*list)[i].top, (*list)[i].right,
831 if (len > sizeof(buf)) break;
832 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
833 kbuf.dsize = strlen(key)+1;
837 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
843 /****************************************************************************
844 add a form struct at the end of the list
845 ****************************************************************************/
846 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
853 * NT tries to add forms even when
854 * they are already in the base
855 * only update the values if already present
860 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
861 for (n=0; n<*count; n++) {
862 if ( strequal((*list)[n].name, form_name) ) {
869 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
870 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
873 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
877 (*list)[n].flag=form->flags;
878 (*list)[n].width=form->size_x;
879 (*list)[n].length=form->size_y;
880 (*list)[n].left=form->left;
881 (*list)[n].top=form->top;
882 (*list)[n].right=form->right;
883 (*list)[n].bottom=form->bottom;
885 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
886 update ? "updated" : "added", form_name));
891 /****************************************************************************
892 Delete a named form struct.
893 ****************************************************************************/
895 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
904 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
906 for (n=0; n<*count; n++) {
907 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
908 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
914 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
915 *ret = WERR_INVALID_PARAM;
919 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
920 kbuf.dsize = strlen(key)+1;
922 if (tdb_delete(tdb_forms, kbuf) != 0) {
930 /****************************************************************************
931 Update a form struct.
932 ****************************************************************************/
934 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
938 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
940 DEBUG(106, ("[%s]\n", form_name));
941 for (n=0; n<count; n++) {
942 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
943 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
947 if (n==count) return;
949 (*list)[n].flag=form->flags;
950 (*list)[n].width=form->size_x;
951 (*list)[n].length=form->size_y;
952 (*list)[n].left=form->left;
953 (*list)[n].top=form->top;
954 (*list)[n].right=form->right;
955 (*list)[n].bottom=form->bottom;
958 /****************************************************************************
959 Get the nt drivers list.
960 Traverse the database and look-up the matching names.
961 ****************************************************************************/
962 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
965 const char *short_archi;
967 TDB_DATA kbuf, newkey;
969 short_archi = get_short_archi(architecture);
974 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
976 for (kbuf = tdb_firstkey(tdb_drivers);
978 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
980 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
983 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
984 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
988 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
995 /****************************************************************************
996 Function to do the mapping between the long architecture name and
998 ****************************************************************************/
1000 const char *get_short_archi(const char *long_archi)
1004 DEBUG(107,("Getting architecture dependant directory\n"));
1007 } while ( (archi_table[i].long_archi!=NULL ) &&
1008 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1010 if (archi_table[i].long_archi==NULL) {
1011 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1015 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1017 DEBUGADD(108,("index: [%d]\n", i));
1018 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1019 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1021 return archi_table[i].short_archi;
1024 /****************************************************************************
1025 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1026 There are two case to be covered here: PE (Portable Executable) and NE (New
1027 Executable) files. Both files support the same INFO structure, but PE files
1028 store the signature in unicode, and NE files store it as !unicode.
1029 returns -1 on error, 1 on version info found, and 0 on no version info found.
1030 ****************************************************************************/
1032 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1038 if ((buf=(char *)SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1039 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1040 fname, PE_HEADER_SIZE));
1044 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1045 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1046 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1047 fname, (unsigned long)byte_count));
1048 goto no_version_info;
1051 /* Is this really a DOS header? */
1052 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1053 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1054 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1055 goto no_version_info;
1058 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1059 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1060 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1062 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1063 goto no_version_info;
1066 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1067 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1068 fname, (unsigned long)byte_count));
1069 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1070 goto no_version_info;
1073 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1074 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1075 unsigned int num_sections;
1076 unsigned int section_table_bytes;
1078 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1079 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1080 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1081 /* At this point, we assume the file is in error. It still could be somthing
1082 * else besides a PE file, but it unlikely at this point.
1087 /* get the section table */
1088 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1089 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1090 if (section_table_bytes == 0)
1094 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1095 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1096 fname, section_table_bytes));
1100 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1101 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1102 fname, (unsigned long)byte_count));
1106 /* Iterate the section table looking for the resource section ".rsrc" */
1107 for (i = 0; i < num_sections; i++) {
1108 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1110 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1111 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1112 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1114 if (section_bytes == 0)
1118 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1119 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1120 fname, section_bytes));
1124 /* Seek to the start of the .rsrc section info */
1125 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1126 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1131 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1132 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1133 fname, (unsigned long)byte_count));
1137 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1140 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1141 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1142 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1143 /* Align to next long address */
1144 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1146 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1147 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1148 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1150 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1151 fname, *major, *minor,
1152 (*major>>16)&0xffff, *major&0xffff,
1153 (*minor>>16)&0xffff, *minor&0xffff));
1162 /* Version info not found, fall back to origin date/time */
1163 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1167 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1168 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1169 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1170 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1171 /* At this point, we assume the file is in error. It still could be somthing
1172 * else besides a NE file, but it unlikely at this point. */
1176 /* Allocate a bit more space to speed up things */
1178 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1179 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1180 fname, PE_HEADER_SIZE));
1184 /* This is a HACK! I got tired of trying to sort through the messy
1185 * 'NE' file format. If anyone wants to clean this up please have at
1186 * it, but this works. 'NE' files will eventually fade away. JRR */
1187 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1188 /* Cover case that should not occur in a well formed 'NE' .dll file */
1189 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1191 for(i=0; i<byte_count; i++) {
1192 /* Fast skip past data that can't possibly match */
1193 if (buf[i] != 'V') continue;
1195 /* Potential match data crosses buf boundry, move it to beginning
1196 * of buf, and fill the buf with as much as it will hold. */
1197 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1200 memcpy(buf, &buf[i], byte_count-i);
1201 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1202 (byte_count-i))) < 0) {
1204 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1209 byte_count = bc + (byte_count - i);
1210 if (byte_count<VS_VERSION_INFO_SIZE) break;
1215 /* Check that the full signature string and the magic number that
1216 * follows exist (not a perfect solution, but the chances that this
1217 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1218 * twice, as it is simpler to read the code. */
1219 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1220 /* Compute skip alignment to next long address */
1221 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1222 sizeof(VS_SIGNATURE)) & 3;
1223 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1225 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1226 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1227 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1228 fname, *major, *minor,
1229 (*major>>16)&0xffff, *major&0xffff,
1230 (*minor>>16)&0xffff, *minor&0xffff));
1237 /* Version info not found, fall back to origin date/time */
1238 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1243 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1244 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1245 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1256 /****************************************************************************
1257 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1258 share one or more files. During the MS installation process files are checked
1259 to insure that only a newer version of a shared file is installed over an
1260 older version. There are several possibilities for this comparison. If there
1261 is no previous version, the new one is newer (obviously). If either file is
1262 missing the version info structure, compare the creation date (on Unix use
1263 the modification date). Otherwise chose the numerically larger version number.
1264 ****************************************************************************/
1266 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1268 BOOL use_version = True;
1273 time_t new_create_time;
1277 time_t old_create_time;
1279 files_struct *fsp = NULL;
1281 SMB_STRUCT_STAT stat_buf;
1286 SET_STAT_INVALID(st);
1287 SET_STAT_INVALID(stat_buf);
1288 new_create_time = (time_t)0;
1289 old_create_time = (time_t)0;
1291 /* Get file version info (if available) for previous file (if it exists) */
1292 pstrcpy(filepath, old_file);
1294 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1296 status = open_file_ntcreate(conn, filepath, &stat_buf,
1298 FILE_SHARE_READ|FILE_SHARE_WRITE,
1301 FILE_ATTRIBUTE_NORMAL,
1305 if (!NT_STATUS_IS_OK(status)) {
1306 /* Old file not found, so by definition new file is in fact newer */
1307 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1312 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1318 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1320 use_version = False;
1321 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1322 old_create_time = st.st_mtime;
1323 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1326 close_file(fsp, NORMAL_CLOSE);
1328 /* Get file version info (if available) for new file */
1329 pstrcpy(filepath, new_file);
1330 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1332 status = open_file_ntcreate(conn, filepath, &stat_buf,
1334 FILE_SHARE_READ|FILE_SHARE_WRITE,
1337 FILE_ATTRIBUTE_NORMAL,
1341 if (!NT_STATUS_IS_OK(status)) {
1342 /* New file not found, this shouldn't occur if the caller did its job */
1343 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1348 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1354 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1356 use_version = False;
1357 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1358 new_create_time = st.st_mtime;
1359 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1362 close_file(fsp, NORMAL_CLOSE);
1364 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1365 /* Compare versions and choose the larger version number */
1366 if (new_major > old_major ||
1367 (new_major == old_major && new_minor > old_minor)) {
1369 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1373 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1378 /* Compare modification time/dates and choose the newest time/date */
1379 if (new_create_time > old_create_time) {
1380 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1384 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1391 close_file(fsp, NORMAL_CLOSE);
1395 /****************************************************************************
1396 Determine the correct cVersion associated with an architecture and driver
1397 ****************************************************************************/
1398 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1399 struct current_user *user, WERROR *perr)
1406 files_struct *fsp = NULL;
1409 connection_struct *conn;
1412 SET_STAT_INVALID(st);
1414 *perr = WERR_INVALID_PARAM;
1416 /* If architecture is Windows 95/98/ME, the version is always 0. */
1417 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1418 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1423 /* If architecture is Windows x64, the version is always 3. */
1424 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1425 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1431 * Connect to the print$ share under the same account as the user connected
1432 * to the rpc pipe. Note we must still be root to do this.
1435 /* Null password is ok - we are already an authenticated user... */
1436 null_pw = data_blob(NULL, 0);
1437 fstrcpy(res_type, "A:");
1439 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1443 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1444 *perr = ntstatus_to_werror(nt_status);
1448 /* We are temporarily becoming the connection user. */
1449 if (!become_user(conn, user->vuid)) {
1450 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1451 *perr = WERR_ACCESS_DENIED;
1455 /* Open the driver file (Portable Executable format) and determine the
1456 * deriver the cversion. */
1457 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1459 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1461 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1462 *perr = WERR_BADFILE;
1466 status = open_file_ntcreate(conn, driverpath, &st,
1468 FILE_SHARE_READ|FILE_SHARE_WRITE,
1471 FILE_ATTRIBUTE_NORMAL,
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1477 driverpath, errno));
1478 *perr = WERR_ACCESS_DENIED;
1483 int ret = get_file_version(fsp, driverpath, &major, &minor);
1484 if (ret == -1) goto error_exit;
1487 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1492 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1493 * for more details. Version in this case is not just the version of the
1494 * file, but the version in the sense of kernal mode (2) vs. user mode
1495 * (3) drivers. Other bits of the version fields are the version info.
1498 cversion = major & 0x0000ffff;
1500 case 2: /* WinNT drivers */
1501 case 3: /* Win2K drivers */
1505 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1506 driverpath, cversion));
1510 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1511 driverpath, major, minor));
1514 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1515 driverpath, cversion));
1517 close_file(fsp, NORMAL_CLOSE);
1518 close_cnum(conn, user->vuid);
1527 close_file(fsp, NORMAL_CLOSE);
1529 close_cnum(conn, user->vuid);
1534 /****************************************************************************
1535 ****************************************************************************/
1536 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1537 struct current_user *user)
1539 const char *architecture;
1545 /* clean up the driver name.
1546 * we can get .\driver.dll
1547 * or worse c:\windows\system\driver.dll !
1549 /* using an intermediate string to not have overlaping memcpy()'s */
1550 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1551 fstrcpy(new_name, p+1);
1552 fstrcpy(driver->driverpath, new_name);
1555 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1556 fstrcpy(new_name, p+1);
1557 fstrcpy(driver->datafile, new_name);
1560 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1561 fstrcpy(new_name, p+1);
1562 fstrcpy(driver->configfile, new_name);
1565 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1566 fstrcpy(new_name, p+1);
1567 fstrcpy(driver->helpfile, new_name);
1570 if (driver->dependentfiles) {
1571 for (i=0; *driver->dependentfiles[i]; i++) {
1572 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1573 fstrcpy(new_name, p+1);
1574 fstrcpy(driver->dependentfiles[i], new_name);
1579 architecture = get_short_archi(driver->environment);
1580 if (!architecture) {
1581 return WERR_UNKNOWN_PRINTER_DRIVER;
1584 /* jfm:7/16/2000 the client always sends the cversion=0.
1585 * The server should check which version the driver is by reading
1586 * the PE header of driver->driverpath.
1588 * For Windows 95/98 the version is 0 (so the value sent is correct)
1589 * For Windows NT (the architecture doesn't matter)
1590 * NT 3.1: cversion=0
1591 * NT 3.5/3.51: cversion=1
1595 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1601 /****************************************************************************
1602 ****************************************************************************/
1603 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1605 const char *architecture;
1611 /* clean up the driver name.
1612 * we can get .\driver.dll
1613 * or worse c:\windows\system\driver.dll !
1615 /* using an intermediate string to not have overlaping memcpy()'s */
1616 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1617 fstrcpy(new_name, p+1);
1618 fstrcpy(driver->driverpath, new_name);
1621 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1622 fstrcpy(new_name, p+1);
1623 fstrcpy(driver->datafile, new_name);
1626 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1627 fstrcpy(new_name, p+1);
1628 fstrcpy(driver->configfile, new_name);
1631 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1632 fstrcpy(new_name, p+1);
1633 fstrcpy(driver->helpfile, new_name);
1636 if (driver->dependentfiles) {
1637 for (i=0; *driver->dependentfiles[i]; i++) {
1638 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1639 fstrcpy(new_name, p+1);
1640 fstrcpy(driver->dependentfiles[i], new_name);
1645 architecture = get_short_archi(driver->environment);
1646 if (!architecture) {
1647 return WERR_UNKNOWN_PRINTER_DRIVER;
1650 /* jfm:7/16/2000 the client always sends the cversion=0.
1651 * The server should check which version the driver is by reading
1652 * the PE header of driver->driverpath.
1654 * For Windows 95/98 the version is 0 (so the value sent is correct)
1655 * For Windows NT (the architecture doesn't matter)
1656 * NT 3.1: cversion=0
1657 * NT 3.5/3.51: cversion=1
1662 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1668 /****************************************************************************
1669 ****************************************************************************/
1670 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1671 uint32 level, struct current_user *user)
1676 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1677 driver=driver_abstract.info_3;
1678 return clean_up_driver_struct_level_3(driver, user);
1682 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1683 driver=driver_abstract.info_6;
1684 return clean_up_driver_struct_level_6(driver, user);
1687 return WERR_INVALID_PARAM;
1691 /****************************************************************************
1692 This function sucks and should be replaced. JRA.
1693 ****************************************************************************/
1695 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1697 dst->cversion = src->version;
1699 fstrcpy( dst->name, src->name);
1700 fstrcpy( dst->environment, src->environment);
1701 fstrcpy( dst->driverpath, src->driverpath);
1702 fstrcpy( dst->datafile, src->datafile);
1703 fstrcpy( dst->configfile, src->configfile);
1704 fstrcpy( dst->helpfile, src->helpfile);
1705 fstrcpy( dst->monitorname, src->monitorname);
1706 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1707 dst->dependentfiles = src->dependentfiles;
1710 #if 0 /* Debugging function */
1712 static char* ffmt(unsigned char *c){
1714 static char ffmt_str[17];
1716 for (i=0; i<16; i++) {
1717 if ((c[i] < ' ') || (c[i] > '~'))
1728 /****************************************************************************
1729 ****************************************************************************/
1730 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1731 struct current_user *user, WERROR *perr)
1733 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1735 const char *architecture;
1740 connection_struct *conn;
1751 memset(inbuf, '\0', sizeof(inbuf));
1752 memset(outbuf, '\0', sizeof(outbuf));
1756 driver=driver_abstract.info_3;
1757 else if (level==6) {
1758 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1759 driver = &converted_driver;
1761 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1762 return WERR_UNKNOWN_LEVEL;
1765 architecture = get_short_archi(driver->environment);
1766 if (!architecture) {
1767 return WERR_UNKNOWN_PRINTER_DRIVER;
1771 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1772 * Note we must be root to do this.
1775 null_pw = data_blob(NULL, 0);
1776 fstrcpy(res_type, "A:");
1778 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1782 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1783 *perr = ntstatus_to_werror(nt_status);
1784 return WERR_NO_SUCH_SHARE;
1788 * Save who we are - we are temporarily becoming the connection user.
1791 if (!become_user(conn, conn->vuid)) {
1792 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1793 return WERR_ACCESS_DENIED;
1797 * make the directories version and version\driver_name
1798 * under the architecture directory.
1800 DEBUG(5,("Creating first directory\n"));
1801 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1802 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1803 mkdir_internal(conn, new_dir, bad_path);
1805 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1806 * listed for this driver which has already been moved, skip it (note:
1807 * drivers may list the same file name several times. Then check if the
1808 * file already exists in archi\cversion\, if so, check that the version
1809 * info (or time stamps if version info is unavailable) is newer (or the
1810 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1811 * Otherwise, delete the file.
1813 * If a file is not moved to archi\cversion\ because of an error, all the
1814 * rest of the 'unmoved' driver files are removed from archi\. If one or
1815 * more of the driver's files was already moved to archi\cversion\, it
1816 * potentially leaves the driver in a partially updated state. Version
1817 * trauma will most likely occur if an client attempts to use any printer
1818 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1819 * done is appropriate... later JRR
1822 DEBUG(5,("Moving files now !\n"));
1824 if (driver->driverpath && strlen(driver->driverpath)) {
1825 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1826 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1827 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1828 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1829 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1830 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1831 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1832 new_name, old_name));
1833 *perr = WERR_ACCESS_DENIED;
1839 if (driver->datafile && strlen(driver->datafile)) {
1840 if (!strequal(driver->datafile, driver->driverpath)) {
1841 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1842 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1843 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1844 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1845 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1846 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1847 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1848 new_name, old_name));
1849 *perr = WERR_ACCESS_DENIED;
1856 if (driver->configfile && strlen(driver->configfile)) {
1857 if (!strequal(driver->configfile, driver->driverpath) &&
1858 !strequal(driver->configfile, driver->datafile)) {
1859 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1860 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1861 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1862 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1863 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1864 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1865 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1866 new_name, old_name));
1867 *perr = WERR_ACCESS_DENIED;
1874 if (driver->helpfile && strlen(driver->helpfile)) {
1875 if (!strequal(driver->helpfile, driver->driverpath) &&
1876 !strequal(driver->helpfile, driver->datafile) &&
1877 !strequal(driver->helpfile, driver->configfile)) {
1878 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1879 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1880 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1881 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1882 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1883 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1884 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1885 new_name, old_name));
1886 *perr = WERR_ACCESS_DENIED;
1893 if (driver->dependentfiles) {
1894 for (i=0; *driver->dependentfiles[i]; i++) {
1895 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1896 !strequal(driver->dependentfiles[i], driver->datafile) &&
1897 !strequal(driver->dependentfiles[i], driver->configfile) &&
1898 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1900 for (j=0; j < i; j++) {
1901 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1906 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1907 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1908 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1909 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1910 if ( !copy_file(new_name, old_name, conn,
1911 OPENX_FILE_EXISTS_TRUNCATE|
1912 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1913 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1914 new_name, old_name));
1915 *perr = WERR_ACCESS_DENIED;
1924 close_cnum(conn, user->vuid);
1927 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1930 /****************************************************************************
1931 ****************************************************************************/
1932 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1935 const char *architecture;
1941 TDB_DATA kbuf, dbuf;
1943 architecture = get_short_archi(driver->environment);
1944 if (!architecture) {
1948 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1949 * \\server is added in the rpc server layer.
1950 * It does make sense to NOT store the server's name in the printer TDB.
1953 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1955 /* .inf files do not always list a file for each of the four standard files.
1956 * Don't prepend a path to a null filename, or client claims:
1957 * "The server on which the printer resides does not have a suitable
1958 * <printer driver name> printer driver installed. Click OK if you
1959 * wish to install the driver on your local machine."
1961 if (strlen(driver->driverpath)) {
1962 fstrcpy(temp_name, driver->driverpath);
1963 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1966 if (strlen(driver->datafile)) {
1967 fstrcpy(temp_name, driver->datafile);
1968 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1971 if (strlen(driver->configfile)) {
1972 fstrcpy(temp_name, driver->configfile);
1973 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1976 if (strlen(driver->helpfile)) {
1977 fstrcpy(temp_name, driver->helpfile);
1978 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1981 if (driver->dependentfiles) {
1982 for (i=0; *driver->dependentfiles[i]; i++) {
1983 fstrcpy(temp_name, driver->dependentfiles[i]);
1984 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1988 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1990 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1997 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2000 driver->environment,
2005 driver->monitorname,
2006 driver->defaultdatatype);
2008 if (driver->dependentfiles) {
2009 for (i=0; *driver->dependentfiles[i]; i++) {
2010 len += tdb_pack(buf+len, buflen-len, "f",
2011 driver->dependentfiles[i]);
2015 if (len != buflen) {
2016 buf = (char *)SMB_REALLOC(buf, len);
2018 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2028 kbuf.dsize = strlen(key)+1;
2032 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
2036 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2042 /****************************************************************************
2043 ****************************************************************************/
2044 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2046 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2049 info3.cversion = driver->version;
2050 fstrcpy(info3.name,driver->name);
2051 fstrcpy(info3.environment,driver->environment);
2052 fstrcpy(info3.driverpath,driver->driverpath);
2053 fstrcpy(info3.datafile,driver->datafile);
2054 fstrcpy(info3.configfile,driver->configfile);
2055 fstrcpy(info3.helpfile,driver->helpfile);
2056 fstrcpy(info3.monitorname,driver->monitorname);
2057 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2058 info3.dependentfiles = driver->dependentfiles;
2060 return add_a_printer_driver_3(&info3);
2064 /****************************************************************************
2065 ****************************************************************************/
2066 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2068 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2072 fstrcpy(info.name, driver);
2073 fstrcpy(info.defaultdatatype, "RAW");
2075 fstrcpy(info.driverpath, "");
2076 fstrcpy(info.datafile, "");
2077 fstrcpy(info.configfile, "");
2078 fstrcpy(info.helpfile, "");
2080 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2083 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2084 fstrcpy(info.dependentfiles[0], "");
2086 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2088 SAFE_FREE(info.dependentfiles);
2095 /****************************************************************************
2096 ****************************************************************************/
2097 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2099 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2100 TDB_DATA kbuf, dbuf;
2101 const char *architecture;
2106 ZERO_STRUCT(driver);
2108 architecture = get_short_archi(arch);
2109 if ( !architecture ) {
2110 return WERR_UNKNOWN_PRINTER_DRIVER;
2113 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2115 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2118 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2120 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2123 kbuf.dsize = strlen(key)+1;
2125 dbuf = tdb_fetch(tdb_drivers, kbuf);
2127 return WERR_UNKNOWN_PRINTER_DRIVER;
2129 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2138 driver.defaultdatatype);
2141 while (len < dbuf.dsize) {
2142 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2143 if ( !driver.dependentfiles ) {
2144 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2148 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2149 &driver.dependentfiles[i]);
2153 if ( driver.dependentfiles )
2154 fstrcpy( driver.dependentfiles[i], "" );
2156 SAFE_FREE(dbuf.dptr);
2158 if (len != dbuf.dsize) {
2159 SAFE_FREE(driver.dependentfiles);
2161 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2164 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2166 SAFE_FREE(driver.dependentfiles);
2173 /****************************************************************************
2174 Debugging function, dump at level 6 the struct in the logs.
2175 ****************************************************************************/
2177 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2180 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2183 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2189 if (driver.info_3 == NULL)
2192 info3=driver.info_3;
2194 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2195 DEBUGADD(20,("name:[%s]\n", info3->name));
2196 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2197 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2198 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2199 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2200 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2201 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2202 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2204 for (i=0; info3->dependentfiles &&
2205 *info3->dependentfiles[i]; i++) {
2206 DEBUGADD(20,("dependentfile:[%s]\n",
2207 info3->dependentfiles[i]));
2214 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2222 /****************************************************************************
2223 ****************************************************************************/
2224 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2228 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2233 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2234 nt_devmode->devicename,
2235 nt_devmode->formname,
2237 nt_devmode->specversion,
2238 nt_devmode->driverversion,
2240 nt_devmode->driverextra,
2241 nt_devmode->orientation,
2242 nt_devmode->papersize,
2243 nt_devmode->paperlength,
2244 nt_devmode->paperwidth,
2247 nt_devmode->defaultsource,
2248 nt_devmode->printquality,
2251 nt_devmode->yresolution,
2252 nt_devmode->ttoption,
2253 nt_devmode->collate,
2254 nt_devmode->logpixels,
2257 nt_devmode->bitsperpel,
2258 nt_devmode->pelswidth,
2259 nt_devmode->pelsheight,
2260 nt_devmode->displayflags,
2261 nt_devmode->displayfrequency,
2262 nt_devmode->icmmethod,
2263 nt_devmode->icmintent,
2264 nt_devmode->mediatype,
2265 nt_devmode->dithertype,
2266 nt_devmode->reserved1,
2267 nt_devmode->reserved2,
2268 nt_devmode->panningwidth,
2269 nt_devmode->panningheight,
2270 nt_devmode->nt_dev_private);
2273 if (nt_devmode->nt_dev_private) {
2274 len += tdb_pack(buf+len, buflen-len, "B",
2275 nt_devmode->driverextra,
2276 nt_devmode->nt_dev_private);
2279 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2284 /****************************************************************************
2285 Pack all values in all printer keys
2286 ***************************************************************************/
2288 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2292 REGISTRY_VALUE *val;
2293 REGVAL_CTR *val_ctr;
2300 /* loop over all keys */
2302 for ( i=0; i<data->num_keys; i++ ) {
2303 val_ctr = data->keys[i].values;
2304 num_values = regval_ctr_numvals( val_ctr );
2306 /* pack the keyname followed by a empty value */
2308 len += tdb_pack(buf+len, buflen-len, "pPdB",
2309 &data->keys[i].name,
2315 /* now loop over all values */
2317 for ( j=0; j<num_values; j++ ) {
2318 /* pathname should be stored as <key>\<value> */
2320 val = regval_ctr_specific_value( val_ctr, j );
2321 pstrcpy( path, data->keys[i].name );
2322 pstrcat( path, "\\" );
2323 pstrcat( path, regval_name(val) );
2325 len += tdb_pack(buf+len, buflen-len, "pPdB",
2330 regval_data_p(val) );
2332 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2339 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2345 /****************************************************************************
2346 Delete a printer - this just deletes the printer info file, any open
2347 handles are not affected.
2348 ****************************************************************************/
2350 uint32 del_a_printer(const char *sharename)
2353 pstring printdb_path;
2355 kbuf = make_printer_tdbkey( sharename );
2356 tdb_delete(tdb_printers, kbuf);
2358 kbuf.dptr = make_printers_secdesc_tdbkey( sharename );
2359 kbuf.dsize = strlen(kbuf.dptr) + 1;
2360 tdb_delete(tdb_printers, kbuf);
2362 close_all_print_db();
2364 if (geteuid() == 0) {
2365 pstrcpy(printdb_path, lock_path("printing/"));
2366 pstrcat(printdb_path, sharename);
2367 pstrcat(printdb_path, ".tdb");
2369 unlink(printdb_path);
2375 /****************************************************************************
2376 ****************************************************************************/
2377 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2382 TDB_DATA kbuf, dbuf;
2385 * in addprinter: no servername and the printer is the name
2386 * in setprinter: servername is \\server
2387 * and printer is \\server\\printer
2389 * Samba manages only local printers.
2390 * we currently don't support things like i
2391 * path=\\other_server\printer
2393 * We only store the printername, not \\server\printername
2396 if ( info->servername[0] != '\0' ) {
2397 trim_string(info->printername, info->servername, NULL);
2398 trim_char(info->printername, '\\', '\0');
2399 info->servername[0]='\0';
2403 * JFM: one day I'll forget.
2404 * below that's info->portname because that's the SAMBA sharename
2405 * and I made NT 'thinks' it's the portname
2406 * the info->sharename is the thing you can name when you add a printer
2407 * that's the short-name when you create shared printer for 95/98
2408 * So I've made a limitation in SAMBA: you can only have 1 printer model
2409 * behind a SAMBA share.
2417 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2420 info->default_priority,
2437 info->printprocessor,
2441 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2443 len += pack_values( info->data, buf+len, buflen-len );
2445 if (buflen != len) {
2446 buf = (char *)SMB_REALLOC(buf, len);
2448 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2457 kbuf = make_printer_tdbkey( info->sharename );
2462 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2465 if (!W_ERROR_IS_OK(ret))
2466 DEBUG(8, ("error updating printer to tdb on disk\n"));
2470 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2471 info->sharename, info->drivername, info->portname, len));
2477 /****************************************************************************
2478 Malloc and return an NT devicemode.
2479 ****************************************************************************/
2481 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2484 char adevice[MAXDEVICENAME];
2485 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2487 if (nt_devmode == NULL) {
2488 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2492 ZERO_STRUCTP(nt_devmode);
2494 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2495 fstrcpy(nt_devmode->devicename, adevice);
2497 fstrcpy(nt_devmode->formname, "Letter");
2499 nt_devmode->specversion = 0x0401;
2500 nt_devmode->driverversion = 0x0400;
2501 nt_devmode->size = 0x00DC;
2502 nt_devmode->driverextra = 0x0000;
2503 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2504 DEFAULTSOURCE | COPIES | SCALE |
2505 PAPERSIZE | ORIENTATION;
2506 nt_devmode->orientation = 1;
2507 nt_devmode->papersize = PAPER_LETTER;
2508 nt_devmode->paperlength = 0;
2509 nt_devmode->paperwidth = 0;
2510 nt_devmode->scale = 0x64;
2511 nt_devmode->copies = 1;
2512 nt_devmode->defaultsource = BIN_FORMSOURCE;
2513 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2514 nt_devmode->color = COLOR_MONOCHROME;
2515 nt_devmode->duplex = DUP_SIMPLEX;
2516 nt_devmode->yresolution = 0;
2517 nt_devmode->ttoption = TT_SUBDEV;
2518 nt_devmode->collate = COLLATE_FALSE;
2519 nt_devmode->icmmethod = 0;
2520 nt_devmode->icmintent = 0;
2521 nt_devmode->mediatype = 0;
2522 nt_devmode->dithertype = 0;
2524 /* non utilisés par un driver d'imprimante */
2525 nt_devmode->logpixels = 0;
2526 nt_devmode->bitsperpel = 0;
2527 nt_devmode->pelswidth = 0;
2528 nt_devmode->pelsheight = 0;
2529 nt_devmode->displayflags = 0;
2530 nt_devmode->displayfrequency = 0;
2531 nt_devmode->reserved1 = 0;
2532 nt_devmode->reserved2 = 0;
2533 nt_devmode->panningwidth = 0;
2534 nt_devmode->panningheight = 0;
2536 nt_devmode->nt_dev_private = NULL;
2540 /****************************************************************************
2541 Deepcopy an NT devicemode.
2542 ****************************************************************************/
2544 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2546 NT_DEVICEMODE *new_nt_devicemode = NULL;
2548 if ( !nt_devicemode )
2551 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2552 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2556 new_nt_devicemode->nt_dev_private = NULL;
2557 if (nt_devicemode->nt_dev_private != NULL) {
2558 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2559 SAFE_FREE(new_nt_devicemode);
2560 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2565 return new_nt_devicemode;
2568 /****************************************************************************
2569 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2570 ****************************************************************************/
2572 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2574 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2576 if(nt_devmode == NULL)
2579 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2581 SAFE_FREE(nt_devmode->nt_dev_private);
2582 SAFE_FREE(*devmode_ptr);
2585 /****************************************************************************
2586 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2587 ****************************************************************************/
2589 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2591 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2596 free_nt_devicemode(&info->devmode);
2598 TALLOC_FREE( *info_ptr );
2602 /****************************************************************************
2603 ****************************************************************************/
2604 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2608 NT_DEVICEMODE devmode;
2610 ZERO_STRUCT(devmode);
2612 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2614 if (!*nt_devmode) return len;
2616 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2620 &devmode.specversion,
2621 &devmode.driverversion,
2623 &devmode.driverextra,
2624 &devmode.orientation,
2626 &devmode.paperlength,
2627 &devmode.paperwidth,
2630 &devmode.defaultsource,
2631 &devmode.printquality,
2634 &devmode.yresolution,
2640 &devmode.bitsperpel,
2642 &devmode.pelsheight,
2643 &devmode.displayflags,
2644 &devmode.displayfrequency,
2648 &devmode.dithertype,
2651 &devmode.panningwidth,
2652 &devmode.panningheight,
2653 &devmode.nt_dev_private);
2655 if (devmode.nt_dev_private) {
2656 /* the len in tdb_unpack is an int value and
2657 * devmode.driverextra is only a short
2659 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2660 devmode.driverextra=(uint16)extra_len;
2662 /* check to catch an invalid TDB entry so we don't segfault */
2663 if (devmode.driverextra == 0) {
2664 devmode.nt_dev_private = NULL;
2668 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2670 SAFE_FREE(devmode.nt_dev_private);
2674 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2675 if (devmode.nt_dev_private)
2676 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2681 /****************************************************************************
2682 Allocate and initialize a new slot.
2683 ***************************************************************************/
2685 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2690 if ( !name || !data )
2693 /* allocate another slot in the NT_PRINTER_KEY array */
2695 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2696 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2702 key_index = data->num_keys;
2704 /* initialze new key */
2706 data->keys[key_index].name = talloc_strdup( data, name );
2708 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2713 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2718 /****************************************************************************
2719 search for a registry key name in the existing printer data
2720 ***************************************************************************/
2722 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2726 for ( i=0; i<data->num_keys; i++ ) {
2727 if ( strequal( data->keys[i].name, name ) ) {
2729 /* cleanup memory */
2731 TALLOC_FREE( data->keys[i].name );
2732 TALLOC_FREE( data->keys[i].values );
2734 /* if not the end of the array, move remaining elements down one slot */
2737 if ( data->num_keys && (i < data->num_keys) )
2738 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2745 return data->num_keys;
2748 /****************************************************************************
2749 search for a registry key name in the existing printer data
2750 ***************************************************************************/
2752 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2757 if ( !data || !name )
2760 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2762 /* loop over all existing keys */
2764 for ( i=0; i<data->num_keys; i++ ) {
2765 if ( strequal(data->keys[i].name, name) ) {
2766 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2776 /****************************************************************************
2777 ***************************************************************************/
2779 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2783 int num_subkeys = 0;
2785 fstring *subkeys_ptr = NULL;
2796 /* special case of asking for the top level printer data registry key names */
2798 if ( strlen(key) == 0 ) {
2799 for ( i=0; i<data->num_keys; i++ ) {
2801 /* found a match, so allocate space and copy the name */
2803 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2804 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2809 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2816 /* asking for the subkeys of some key */
2817 /* subkey paths are stored in the key name using '\' as the delimiter */
2819 for ( i=0; i<data->num_keys; i++ ) {
2820 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2822 /* if we found the exact key, then break */
2823 key_len = strlen( key );
2824 if ( strlen(data->keys[i].name) == key_len )
2827 /* get subkey path */
2829 p = data->keys[i].name + key_len;
2832 fstrcpy( subkeyname, p );
2833 if ( (p = strchr( subkeyname, '\\' )) )
2836 /* don't add a key more than once */
2838 for ( j=0; j<num_subkeys; j++ ) {
2839 if ( strequal( subkeys_ptr[j], subkeyname ) )
2843 if ( j != num_subkeys )
2846 /* found a match, so allocate space and copy the name */
2848 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2849 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2854 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2860 /* return error if the key was not found */
2862 if ( i == data->num_keys ) {
2863 SAFE_FREE(subkeys_ptr);
2868 /* tag off the end */
2871 fstrcpy(subkeys_ptr[num_subkeys], "" );
2873 *subkeys = subkeys_ptr;
2879 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2882 smb_ucs2_t conv_str[1024];
2885 regval_ctr_delvalue(ctr, val_name);
2886 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2887 STR_TERMINATE | STR_NOALIGN);
2888 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2889 (char *) conv_str, str_size);
2892 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2895 regval_ctr_delvalue(ctr, val_name);
2896 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2897 (char *) &dword, sizeof(dword));
2900 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2903 uint8 bin_bool = (b ? 1 : 0);
2904 regval_ctr_delvalue(ctr, val_name);
2905 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2906 (char *) &bin_bool, sizeof(bin_bool));
2909 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2910 const char *multi_sz)
2912 smb_ucs2_t *conv_strs = NULL;
2915 /* a multi-sz has to have a null string terminator, i.e., the last
2916 string must be followed by two nulls */
2917 str_size = strlen(multi_sz) + 2;
2918 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2923 /* Change to byte units. */
2924 str_size *= sizeof(smb_ucs2_t);
2925 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2926 STR_TERMINATE | STR_NOALIGN);
2928 regval_ctr_delvalue(ctr, val_name);
2929 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2930 (char *) conv_strs, str_size);
2931 safe_free(conv_strs);
2935 /****************************************************************************
2936 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2938 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2939 * @return BOOL indicating success or failure
2940 ***************************************************************************/
2942 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2944 REGVAL_CTR *ctr = NULL;
2947 char *allocated_string = NULL;
2948 const char *ascii_str;
2951 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2952 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2953 ctr = info2->data->keys[i].values;
2955 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2956 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2958 /* we make the assumption that the netbios name is the same
2959 as the DNS name sinc ethe former will be what we used to
2962 if ( get_mydnsdomname( dnssuffix ) )
2963 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2965 fstrcpy( longname, global_myname() );
2967 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2969 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2970 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2971 SAFE_FREE(allocated_string);
2973 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2974 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2975 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2976 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2977 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2978 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2979 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2980 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2981 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2983 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2984 (info2->attributes &
2985 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2987 switch (info2->attributes & 0x3) {
2989 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2992 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2995 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2998 ascii_str = "unknown";
3000 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3005 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3009 REGVAL_CTR *ctr=NULL;
3011 /* find the DsSpooler key */
3012 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3013 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3014 ctr = info2->data->keys[i].values;
3016 regval_ctr_delvalue(ctr, "objectGUID");
3017 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
3018 (char *) &guid, sizeof(struct uuid));
3021 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3022 NT_PRINTER_INFO_LEVEL *printer)
3026 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
3027 char *srv_dn_utf8, **srv_cn_utf8;
3030 const char *attrs[] = {"objectGUID", NULL};
3032 WERROR win_rc = WERR_OK;
3034 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3036 /* figure out where to publish */
3037 ads_find_machine_acct(ads, &res, global_myname());
3039 /* We use ldap_get_dn here as we need the answer
3040 * in utf8 to call ldap_explode_dn(). JRA. */
3042 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
3045 return WERR_SERVER_UNAVAILABLE;
3047 ads_msgfree(ads, res);
3048 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3050 ldap_memfree(srv_dn_utf8);
3052 return WERR_SERVER_UNAVAILABLE;
3054 /* Now convert to CH_UNIX. */
3055 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3056 ldap_memfree(srv_dn_utf8);
3057 ldap_memfree(srv_cn_utf8);
3059 return WERR_SERVER_UNAVAILABLE;
3061 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3062 ldap_memfree(srv_dn_utf8);
3063 ldap_memfree(srv_cn_utf8);
3066 return WERR_SERVER_UNAVAILABLE;
3069 ldap_memfree(srv_dn_utf8);
3070 ldap_memfree(srv_cn_utf8);
3072 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
3073 printer->info_2->sharename, srv_dn);
3076 SAFE_FREE(srv_cn_0);
3078 /* build the ads mods */
3079 ctx = talloc_init("nt_printer_publish_ads");
3085 mods = ads_init_mods(ctx);
3089 talloc_destroy(ctx);
3093 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3094 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3095 printer->info_2->sharename);
3098 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3099 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3100 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3102 if (!ADS_ERR_OK(ads_rc))
3103 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3105 talloc_destroy(ctx);
3107 /* retreive the guid and store it locally */
3108 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3110 ads_pull_guid(ads, res, &guid);
3111 ads_msgfree(ads, res);
3112 store_printer_guid(printer->info_2, guid);
3113 win_rc = mod_a_printer(printer, 2);
3120 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3121 NT_PRINTER_INFO_LEVEL *printer)
3125 char *prt_dn = NULL;
3127 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3129 /* remove the printer from the directory */
3130 ads_rc = ads_find_printer_on_server(ads, &res,
3131 printer->info_2->sharename, global_myname());
3133 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3134 prt_dn = ads_get_dn(ads, res);
3136 ads_msgfree(ads, res);
3139 ads_rc = ads_del_dn(ads, prt_dn);
3140 ads_memfree(ads, prt_dn);
3143 ads_msgfree(ads, res);
3147 /****************************************************************************
3148 * Publish a printer in the directory
3150 * @param snum describing printer service
3151 * @return WERROR indicating status of publishing
3152 ***************************************************************************/
3154 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3157 ADS_STRUCT *ads = NULL;
3158 NT_PRINTER_INFO_LEVEL *printer = NULL;
3161 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3162 if (!W_ERROR_IS_OK(win_rc))
3166 case SPOOL_DS_PUBLISH:
3167 case SPOOL_DS_UPDATE:
3168 /* set the DsSpooler info and attributes */
3169 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3170 win_rc = WERR_NOMEM;
3174 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3176 case SPOOL_DS_UNPUBLISH:
3177 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3180 win_rc = WERR_NOT_SUPPORTED;
3184 win_rc = mod_a_printer(printer, 2);
3185 if (!W_ERROR_IS_OK(win_rc)) {
3186 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3190 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3192 DEBUG(3, ("ads_init() failed\n"));
3193 win_rc = WERR_SERVER_UNAVAILABLE;
3196 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3197 SAFE_FREE(ads->auth.password);
3198 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3201 /* ads_connect() will find the DC for us */
3202 ads_rc = ads_connect(ads);
3203 if (!ADS_ERR_OK(ads_rc)) {
3204 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3205 win_rc = WERR_ACCESS_DENIED;
3210 case SPOOL_DS_PUBLISH:
3211 case SPOOL_DS_UPDATE:
3212 win_rc = nt_printer_publish_ads(ads, printer);
3214 case SPOOL_DS_UNPUBLISH:
3215 win_rc = nt_printer_unpublish_ads(ads, printer);
3220 free_a_printer(&printer, 2);
3225 WERROR check_published_printers(void)
3228 ADS_STRUCT *ads = NULL;
3230 int n_services = lp_numservices();
3231 NT_PRINTER_INFO_LEVEL *printer = NULL;
3233 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3235 DEBUG(3, ("ads_init() failed\n"));
3236 return WERR_SERVER_UNAVAILABLE;
3238 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3239 SAFE_FREE(ads->auth.password);
3240 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3243 /* ads_connect() will find the DC for us */
3244 ads_rc = ads_connect(ads);
3245 if (!ADS_ERR_OK(ads_rc)) {
3246 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3248 return WERR_ACCESS_DENIED;
3251 for (snum = 0; snum < n_services; snum++) {
3252 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3255 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3256 lp_servicename(snum))) &&
3257 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3258 nt_printer_publish_ads(ads, printer);
3260 free_a_printer(&printer, 2);
3267 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3270 NT_PRINTER_INFO_LEVEL *printer = NULL;
3272 REGISTRY_VALUE *guid_val;
3276 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3278 if (!W_ERROR_IS_OK(win_rc) ||
3279 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3280 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3281 !(ctr = printer->info_2->data->keys[i].values) ||
3282 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3284 free_a_printer(&printer, 2);
3288 /* fetching printer guids really ought to be a separate function.. */
3289 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3290 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3292 free_a_printer(&printer, 2);
3296 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3301 WERROR check_published_printers(void)
3306 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3311 #endif /* HAVE_ADS */
3313 /****************************************************************************
3314 ***************************************************************************/
3316 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3318 NT_PRINTER_DATA *data;
3320 int removed_keys = 0;
3324 empty_slot = data->num_keys;
3327 return WERR_INVALID_PARAM;
3329 /* remove all keys */
3331 if ( !strlen(key) ) {
3333 TALLOC_FREE( data );
3337 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3343 /* remove a specific key (and all subkeys) */
3345 for ( i=0; i<data->num_keys; i++ ) {
3346 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3347 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3348 data->keys[i].name));
3350 TALLOC_FREE( data->keys[i].name );
3351 TALLOC_FREE( data->keys[i].values );
3353 /* mark the slot as empty */
3355 ZERO_STRUCTP( &data->keys[i] );
3359 /* find the first empty slot */
3361 for ( i=0; i<data->num_keys; i++ ) {
3362 if ( !data->keys[i].name ) {
3369 if ( i == data->num_keys )
3370 /* nothing was removed */
3371 return WERR_INVALID_PARAM;
3373 /* move everything down */
3375 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3376 if ( data->keys[i].name ) {
3377 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3378 ZERO_STRUCTP( &data->keys[i] );
3386 data->num_keys -= removed_keys;
3388 /* sanity check to see if anything is left */
3390 if ( !data->num_keys ) {
3391 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3393 SAFE_FREE( data->keys );
3394 ZERO_STRUCTP( data );
3400 /****************************************************************************
3401 ***************************************************************************/
3403 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3405 WERROR result = WERR_OK;
3408 /* we must have names on non-zero length */
3410 if ( !key || !*key|| !value || !*value )
3411 return WERR_INVALID_NAME;
3413 /* find the printer key first */
3415 key_index = lookup_printerkey( p2->data, key );
3416 if ( key_index == -1 )
3419 /* make sure the value exists so we can return the correct error code */
3421 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3422 return WERR_BADFILE;
3424 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3426 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3432 /****************************************************************************
3433 ***************************************************************************/
3435 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3436 uint32 type, uint8 *data, int real_len )
3438 WERROR result = WERR_OK;
3441 /* we must have names on non-zero length */
3443 if ( !key || !*key|| !value || !*value )
3444 return WERR_INVALID_NAME;
3446 /* find the printer key first */
3448 key_index = lookup_printerkey( p2->data, key );
3449 if ( key_index == -1 )
3450 key_index = add_new_printer_key( p2->data, key );
3452 if ( key_index == -1 )
3455 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3456 type, (const char *)data, real_len );
3458 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3459 key, value, type, real_len ));
3464 /****************************************************************************
3465 ***************************************************************************/
3467 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3471 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3474 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3477 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3480 /****************************************************************************
3481 Unpack a list of registry values frem the TDB
3482 ***************************************************************************/
3484 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3488 pstring string, valuename, keyname;
3492 REGISTRY_VALUE *regval_p;
3495 /* add the "PrinterDriverData" key first for performance reasons */
3497 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3499 /* loop and unpack the rest of the registry values */
3503 /* check to see if there are any more registry values */
3506 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3510 /* unpack the next regval */
3512 len += tdb_unpack(buf+len, buflen-len, "fdB",
3518 /* lookup for subkey names which have a type of REG_NONE */
3519 /* there's no data with this entry */
3521 if ( type == REG_NONE ) {
3522 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3523 add_new_printer_key( printer_data, string );
3528 * break of the keyname from the value name.
3529 * Valuenames can have embedded '\'s so be careful.
3530 * only support one level of keys. See the
3531 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3535 str = strchr_m( string, '\\');
3537 /* Put in "PrinterDriverData" is no key specified */
3540 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3541 pstrcpy( valuename, string );
3545 pstrcpy( keyname, string );
3546 pstrcpy( valuename, str+1 );
3549 /* see if we need a new key */
3551 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3552 key_index = add_new_printer_key( printer_data, keyname );
3554 if ( key_index == -1 ) {
3555 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3560 /* add the new value */
3562 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3564 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3566 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3572 /****************************************************************************
3573 ***************************************************************************/
3575 static void map_to_os2_driver(fstring drivername)
3577 static BOOL initialised=False;
3578 static fstring last_from,last_to;
3579 char *mapfile = lp_os2_driver_map();
3580 char **lines = NULL;
3584 if (!strlen(drivername))
3591 *last_from = *last_to = 0;
3595 if (strequal(drivername,last_from)) {
3596 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3597 fstrcpy(drivername,last_to);
3601 lines = file_lines_load(mapfile, &numlines,0);
3602 if (numlines == 0 || lines == NULL) {
3603 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3608 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3610 for( i = 0; i < numlines; i++) {
3611 char *nt_name = lines[i];
3612 char *os2_name = strchr(nt_name,'=');
3619 while (isspace(*nt_name))
3622 if (!*nt_name || strchr("#;",*nt_name))
3626 int l = strlen(nt_name);
3627 while (l && isspace(nt_name[l-1])) {
3633 while (isspace(*os2_name))
3637 int l = strlen(os2_name);
3638 while (l && isspace(os2_name[l-1])) {
3644 if (strequal(nt_name,drivername)) {
3645 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3646 fstrcpy(last_from,drivername);
3647 fstrcpy(last_to,os2_name);
3648 fstrcpy(drivername,os2_name);
3649 file_lines_free(lines);
3654 file_lines_free(lines);
3657 /****************************************************************************
3658 Get a default printer info 2 struct.
3659 ****************************************************************************/
3660 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3664 snum = lp_servicenumber(sharename);
3666 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3667 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3668 servername, sharename);
3669 fstrcpy(info->sharename, sharename);
3670 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3672 /* by setting the driver name to an empty string, a local NT admin
3673 can now run the **local** APW to install a local printer driver
3674 for a Samba shared printer in 2.2. Without this, drivers **must** be
3675 installed on the Samba server for NT clients --jerry */
3676 #if 0 /* JERRY --do not uncomment-- */
3677 if (!*info->drivername)
3678 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3682 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3684 pstrcpy(info->comment, "");
3685 fstrcpy(info->printprocessor, "winprint");
3686 fstrcpy(info->datatype, "RAW");
3688 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3690 info->starttime = 0; /* Minutes since 12:00am GMT */
3691 info->untiltime = 0; /* Minutes since 12:00am GMT */
3693 info->default_priority = 1;
3694 info->setuptime = (uint32)time(NULL);
3697 * I changed this as I think it is better to have a generic
3698 * DEVMODE than to crash Win2k explorer.exe --jerry
3699 * See the HP Deskjet 990c Win2k drivers for an example.
3701 * However the default devmode appears to cause problems
3702 * with the HP CLJ 8500 PCL driver. Hence the addition of
3703 * the "default devmode" parameter --jerry 22/01/2002
3706 if (lp_default_devmode(snum)) {
3707 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3711 info->devmode = NULL;
3714 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3722 free_nt_devicemode(&info->devmode);
3724 return WERR_ACCESS_DENIED;
3727 /****************************************************************************
3728 ****************************************************************************/
3729 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3732 int snum = lp_servicenumber(sharename);
3733 TDB_DATA kbuf, dbuf;
3734 fstring printername;
3735 char adevice[MAXDEVICENAME];
3737 kbuf = make_printer_tdbkey( sharename );
3739 dbuf = tdb_fetch(tdb_printers, kbuf);
3741 return get_a_printer_2_default(info, servername, sharename);
3744 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3747 &info->default_priority,
3754 &info->c_setprinter,
3764 info->printprocessor,
3768 /* Samba has to have shared raw drivers. */
3769 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3770 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3772 /* Restore the stripped strings. */
3773 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3775 if ( lp_force_printername(snum) ) {
3776 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3778 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3781 fstrcpy(info->printername, printername);
3783 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3786 * Some client drivers freak out if there is a NULL devmode
3787 * (probably the driver is not checking before accessing
3788 * the devmode pointer) --jerry
3790 * See comments in get_a_printer_2_default()
3793 if (lp_default_devmode(snum) && !info->devmode) {
3794 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3796 info->devmode = construct_nt_devicemode(printername);
3799 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3800 if (info->devmode) {
3801 fstrcpy(info->devmode->devicename, adevice);
3804 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3805 DEBUG(0,("unpack_values: talloc() failed!\n"));
3806 SAFE_FREE(dbuf.dptr);
3809 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3811 /* This will get the current RPC talloc context, but we should be
3812 passing this as a parameter... fixme... JRA ! */
3814 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3815 SAFE_FREE(dbuf.dptr);
3819 /* Fix for OS/2 drivers. */
3821 if (get_remote_arch() == RA_OS2) {
3822 map_to_os2_driver(info->drivername);
3825 SAFE_FREE(dbuf.dptr);
3827 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3828 sharename, info->printername, info->drivername));
3833 /****************************************************************************
3834 Debugging function, dump at level 6 the struct in the logs.
3835 ****************************************************************************/
3836 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3839 NT_PRINTER_INFO_LEVEL_2 *info2;
3841 DEBUG(106,("Dumping printer at level [%d]\n", level));
3846 if (printer->info_2 == NULL)
3850 info2=printer->info_2;
3852 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3853 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3854 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3855 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3856 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3857 DEBUGADD(106,("status:[%d]\n", info2->status));
3858 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3859 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3860 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3861 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3862 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3864 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3865 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3866 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3867 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3868 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3869 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3870 DEBUGADD(106,("location:[%s]\n", info2->location));
3871 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3872 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3873 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3874 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3880 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3888 /****************************************************************************
3889 Update the changeid time.
3890 This is SO NASTY as some drivers need this to change, others need it
3891 static. This value will change every second, and I must hope that this
3892 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3894 ****************************************************************************/
3896 static uint32 rev_changeid(void)
3900 get_process_uptime(&tv);
3903 /* Return changeid as msec since spooler restart */
3904 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3907 * This setting seems to work well but is too untested
3908 * to replace the above calculation. Left in for experiementation
3909 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3911 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3917 * The function below are the high level ones.
3918 * only those ones must be called from the spoolss code.
3922 /****************************************************************************
3923 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3924 ****************************************************************************/
3926 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3930 dump_a_printer(printer, level);
3936 * Update the changestamp. Emperical tests show that the
3937 * ChangeID is always updated,but c_setprinter is
3938 * global spooler variable (not per printer).
3941 /* ChangeID **must** be increasing over the lifetime
3942 of client's spoolss service in order for the
3943 client's cache to show updates */
3945 printer->info_2->changeid = rev_changeid();
3948 * Because one day someone will ask:
3949 * NT->NT An admin connection to a remote
3950 * printer show changes imeediately in
3951 * the properities dialog
3953 * A non-admin connection will only show the
3954 * changes after viewing the properites page
3955 * 2 times. Seems to be related to a
3956 * race condition in the client between the spooler
3957 * updating the local cache and the Explorer.exe GUI
3958 * actually displaying the properties.
3960 * This is fixed in Win2k. admin/non-admin
3961 * connections both display changes immediately.
3966 result=update_a_printer_2(printer->info_2);
3971 result=WERR_UNKNOWN_LEVEL;
3978 /****************************************************************************
3979 Initialize printer devmode & data with previously saved driver init values.
3980 ****************************************************************************/
3982 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3986 TDB_DATA kbuf, dbuf;
3987 NT_PRINTER_INFO_LEVEL_2 info;
3993 * Delete any printer data 'values' already set. When called for driver
3994 * replace, there will generally be some, but during an add printer, there
3995 * should not be any (if there are delete them).
3998 if ( info_ptr->data )
3999 delete_all_printer_data( info_ptr, "" );
4001 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4004 kbuf.dsize = strlen(key)+1;
4006 dbuf = tdb_fetch(tdb_drivers, kbuf);
4009 * When changing to a driver that has no init info in the tdb, remove
4010 * the previous drivers init info and leave the new on blank.
4012 free_nt_devicemode(&info_ptr->devmode);
4017 * Get the saved DEVMODE..
4020 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4023 * The saved DEVMODE contains the devicename from the printer used during
4024 * the initialization save. Change it to reflect the new printer.
4027 if ( info.devmode ) {
4028 ZERO_STRUCT(info.devmode->devicename);
4029 fstrcpy(info.devmode->devicename, info_ptr->printername);
4033 * NT/2k does not change out the entire DeviceMode of a printer
4034 * when changing the driver. Only the driverextra, private, &
4035 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4037 * Later examination revealed that Windows NT/2k does reset the
4038 * the printer's device mode, bit **only** when you change a
4039 * property of the device mode such as the page orientation.
4044 /* Bind the saved DEVMODE to the new the printer */
4046 free_nt_devicemode(&info_ptr->devmode);
4047 info_ptr->devmode = info.devmode;
4049 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4050 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4052 /* Add the printer data 'values' to the new printer */
4054 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4055 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4059 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4062 SAFE_FREE(dbuf.dptr);
4067 /****************************************************************************
4068 Initialize printer devmode & data with previously saved driver init values.
4069 When a printer is created using AddPrinter, the drivername bound to the
4070 printer is used to lookup previously saved driver initialization info, which
4071 is bound to the new printer.
4072 ****************************************************************************/
4074 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4076 BOOL result = False;
4080 result = set_driver_init_2(printer->info_2);
4084 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4092 /****************************************************************************
4093 Delete driver init data stored for a specified driver
4094 ****************************************************************************/
4096 BOOL del_driver_init(char *drivername)
4101 if (!drivername || !*drivername) {
4102 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4106 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4109 kbuf.dsize = strlen(key)+1;
4111 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4113 return (tdb_delete(tdb_drivers, kbuf) == 0);
4116 /****************************************************************************
4117 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4118 in the tdb. Note: this is different from the driver entry and the printer
4119 entry. There should be a single driver init entry for each driver regardless
4120 of whether it was installed from NT or 2K. Technically, they should be
4121 different, but they work out to the same struct.
4122 ****************************************************************************/
4124 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4128 int buflen, len, ret;
4129 TDB_DATA kbuf, dbuf;
4136 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4138 len += pack_values( info->data, buf+len, buflen-len );
4141 buf = (char *)SMB_REALLOC(buf, len);
4143 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4151 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4154 kbuf.dsize = strlen(key)+1;
4158 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4162 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4166 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4167 info->sharename, info->drivername));
4172 /****************************************************************************
4173 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4174 ****************************************************************************/
4176 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4180 dump_a_printer(printer, level);
4184 result = update_driver_init_2(printer->info_2);
4194 /****************************************************************************
4195 Convert the printer data value, a REG_BINARY array, into an initialization
4196 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4197 got to keep the endians happy :).
4198 ****************************************************************************/
4200 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4202 BOOL result = False;
4206 ZERO_STRUCT(devmode);
4208 prs_init(&ps, 0, ctx, UNMARSHALL);
4209 ps.data_p = (char *)data;
4210 ps.buffer_size = data_len;
4212 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4213 result = convert_devicemode("", &devmode, &nt_devmode);
4215 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4220 /****************************************************************************
4221 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4223 1. Use the driver's config DLL to this UNC printername and:
4224 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4225 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4226 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4228 The last step triggers saving the "driver initialization" information for
4229 this printer into the tdb. Later, new printers that use this driver will
4230 have this initialization information bound to them. This simulates the
4231 driver initialization, as if it had run on the Samba server (as it would
4234 The Win32 client side code requirement sucks! But until we can run arbitrary
4235 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4237 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4238 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4239 about it and you will realize why. JRR 010720
4240 ****************************************************************************/
4242 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4244 WERROR status = WERR_OK;
4245 TALLOC_CTX *ctx = NULL;
4246 NT_DEVICEMODE *nt_devmode = NULL;
4247 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4250 * When the DEVMODE is already set on the printer, don't try to unpack it.
4252 DEBUG(8,("save_driver_init_2: Enter...\n"));
4254 if ( !printer->info_2->devmode && data_len ) {
4256 * Set devmode on printer info, so entire printer initialization can be
4260 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4263 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4264 status = WERR_NOMEM;
4268 ZERO_STRUCTP(nt_devmode);
4271 * The DEVMODE is held in the 'data' component of the param in raw binary.
4272 * Convert it to to a devmode structure
4274 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4275 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4276 status = WERR_INVALID_PARAM;
4280 printer->info_2->devmode = nt_devmode;
4284 * Pack up and add (or update) the DEVMODE and any current printer data to
4285 * a 'driver init' element in the tdb
4289 if ( update_driver_init(printer, 2) != 0 ) {
4290 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4291 status = WERR_NOMEM;
4296 * If driver initialization info was successfully saved, set the current
4297 * printer to match it. This allows initialization of the current printer
4298 * as well as the driver.
4300 status = mod_a_printer(printer, 2);
4301 if (!W_ERROR_IS_OK(status)) {
4302 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4303 printer->info_2->printername));
4307 talloc_destroy(ctx);
4308 free_nt_devicemode( &nt_devmode );
4310 printer->info_2->devmode = tmp_devmode;
4315 /****************************************************************************
4316 Update the driver init info (DEVMODE and specifics) for a printer
4317 ****************************************************************************/
4319 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4321 WERROR status = WERR_OK;
4325 status = save_driver_init_2( printer, data, data_len );
4328 status = WERR_UNKNOWN_LEVEL;
4335 /****************************************************************************
4336 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4338 Previously the code had a memory allocation problem because it always
4339 used the TALLOC_CTX from the Printer_entry*. This context lasts
4340 as a long as the original handle is open. So if the client made a lot
4341 of getprinter[data]() calls, the memory usage would climb. Now we use
4342 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4343 still use the Printer_entry->ctx for maintaining the cache copy though
4344 since that object must live as long as the handle by definition.
4347 ****************************************************************************/
4349 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4350 const char *sharename)
4355 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4357 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4358 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4364 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4365 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4366 TALLOC_FREE( *pp_printer );
4371 fstrcpy( servername, print_hnd->servername );
4373 fstrcpy( servername, "%L" );
4374 standard_sub_basic( "", "", servername,
4375 sizeof(servername)-1 );
4378 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4381 /* we have a new printer now. Save it with this handle */
4383 if ( !W_ERROR_IS_OK(result) ) {
4384 TALLOC_FREE( *pp_printer );
4385 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4386 sharename, (unsigned int)level, dos_errstr(result)));
4390 dump_a_printer( *pp_printer, level);
4395 TALLOC_FREE( *pp_printer );
4396 return WERR_UNKNOWN_LEVEL;
4402 /****************************************************************************
4403 Deletes a NT_PRINTER_INFO_LEVEL struct.
4404 ****************************************************************************/
4406 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4408 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4415 if ( printer->info_2 )
4416 free_nt_printer_info_level_2(&printer->info_2);
4420 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4424 TALLOC_FREE(*pp_printer);
4429 /****************************************************************************
4430 ****************************************************************************/
4431 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4434 DEBUG(104,("adding a printer at level [%d]\n", level));
4435 dump_a_printer_driver(driver, level);
4439 result=add_a_printer_driver_3(driver.info_3);
4443 result=add_a_printer_driver_6(driver.info_6);
4453 /****************************************************************************
4454 ****************************************************************************/
4456 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4457 fstring drivername, const char *architecture, uint32 version)
4463 /* Sometime we just want any version of the driver */
4465 if ( version == DRIVER_ANY_VERSION ) {
4466 /* look for Win2k first and then for NT4 */
4467 result = get_a_printer_driver_3(&driver->info_3, drivername,
4470 if ( !W_ERROR_IS_OK(result) ) {
4471 result = get_a_printer_driver_3( &driver->info_3,
4472 drivername, architecture, 2 );
4475 result = get_a_printer_driver_3(&driver->info_3, drivername,
4476 architecture, version);
4485 if (W_ERROR_IS_OK(result))
4486 dump_a_printer_driver(*driver, level);
4491 /****************************************************************************
4492 ****************************************************************************/
4493 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4500 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4501 if (driver.info_3 != NULL)
4503 info3=driver.info_3;
4504 SAFE_FREE(info3->dependentfiles);
4505 ZERO_STRUCTP(info3);
4515 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4516 if (driver.info_6 != NULL) {
4517 info6=driver.info_6;
4518 SAFE_FREE(info6->dependentfiles);
4519 SAFE_FREE(info6->previousnames);
4520 ZERO_STRUCTP(info6);
4536 /****************************************************************************
4537 Determine whether or not a particular driver is currently assigned
4539 ****************************************************************************/
4541 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4544 int n_services = lp_numservices();
4545 NT_PRINTER_INFO_LEVEL *printer = NULL;
4546 BOOL in_use = False;
4551 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4553 /* loop through the printers.tdb and check for the drivername */
4555 for (snum=0; snum<n_services && !in_use; snum++) {
4556 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4559 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4562 if ( strequal(info_3->name, printer->info_2->drivername) )
4565 free_a_printer( &printer, 2 );
4568 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4571 NT_PRINTER_DRIVER_INFO_LEVEL d;
4574 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4576 /* we can still remove the driver if there is one of
4577 "Windows NT x86" version 2 or 3 left */
4579 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4580 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4583 switch ( info_3->cversion ) {
4585 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4588 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4591 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4593 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4598 /* now check the error code */
4600 if ( W_ERROR_IS_OK(werr) ) {
4601 /* it's ok to remove the driver, we have other architctures left */
4603 free_a_printer_driver( d, 3 );
4607 /* report that the driver is not in use by default */
4613 /**********************************************************************
4614 Check to see if a ogiven file is in use by *info
4615 *********************************************************************/
4617 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4624 if ( strequal(file, info->driverpath) )
4627 if ( strequal(file, info->datafile) )
4630 if ( strequal(file, info->configfile) )
4633 if ( strequal(file, info->helpfile) )
4636 /* see of there are any dependent files to examine */
4638 if ( !info->dependentfiles )
4641 while ( *info->dependentfiles[i] ) {
4642 if ( strequal(file, info->dependentfiles[i]) )
4651 /**********************************************************************
4652 Utility function to remove the dependent file pointed to by the
4653 input parameter from the list
4654 *********************************************************************/
4656 static void trim_dependent_file( fstring files[], int idx )
4659 /* bump everything down a slot */
4661 while( *files[idx+1] ) {
4662 fstrcpy( files[idx], files[idx+1] );
4671 /**********************************************************************
4672 Check if any of the files used by src are also used by drv
4673 *********************************************************************/
4675 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4676 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4678 BOOL in_use = False;
4684 /* check each file. Remove it from the src structure if it overlaps */
4686 if ( drv_file_in_use(src->driverpath, drv) ) {
4688 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4689 fstrcpy( src->driverpath, "" );
4692 if ( drv_file_in_use(src->datafile, drv) ) {
4694 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4695 fstrcpy( src->datafile, "" );
4698 if ( drv_file_in_use(src->configfile, drv) ) {
4700 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4701 fstrcpy( src->configfile, "" );
4704 if ( drv_file_in_use(src->helpfile, drv) ) {
4706 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4707 fstrcpy( src->helpfile, "" );
4710 /* are there any dependentfiles to examine? */
4712 if ( !src->dependentfiles )
4715 while ( *src->dependentfiles[i] ) {
4716 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4718 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4719 trim_dependent_file( src->dependentfiles, i );
4727 /****************************************************************************
4728 Determine whether or not a particular driver files are currently being
4729 used by any other driver.
4731 Return value is True if any files were in use by other drivers
4732 and False otherwise.
4734 Upon return, *info has been modified to only contain the driver files
4735 which are not in use
4736 ****************************************************************************/
4738 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4743 fstring *list = NULL;
4744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4749 version = info->cversion;
4751 /* loop over all driver versions */
4753 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4755 /* get the list of drivers */
4758 ndrivers = get_ntdrivers(&list, info->environment, version);
4760 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4761 ndrivers, info->environment, version));
4763 /* check each driver for overlap in files */
4765 for (i=0; i<ndrivers; i++) {
4766 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4768 ZERO_STRUCT(driver);
4770 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4775 /* check if d2 uses any files from d1 */
4776 /* only if this is a different driver than the one being deleted */
4778 if ( !strequal(info->name, driver.info_3->name) ) {
4779 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4780 free_a_printer_driver(driver, 3);
4786 free_a_printer_driver(driver, 3);
4791 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4793 driver.info_3 = info;
4795 if ( DEBUGLEVEL >= 20 )
4796 dump_a_printer_driver( driver, 3 );
4801 /****************************************************************************
4802 Actually delete the driver files. Make sure that
4803 printer_driver_files_in_use() return False before calling
4805 ****************************************************************************/
4807 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4812 connection_struct *conn;
4822 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4825 * Connect to the print$ share under the same account as the
4826 * user connected to the rpc pipe. Note we must be root to
4830 null_pw = data_blob( NULL, 0 );
4831 fstrcpy(res_type, "A:");
4833 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4837 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4841 if ( !CAN_WRITE(conn) ) {
4842 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4846 /* Save who we are - we are temporarily becoming the connection user. */
4848 if ( !become_user(conn, conn->vuid) ) {
4849 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4853 /* now delete the files; must strip the '\print$' string from
4856 if ( *info_3->driverpath ) {
4857 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4859 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4860 DEBUG(10,("deleting driverfile [%s]\n", s));
4861 unlink_internals(conn, 0, file, False);
4865 if ( *info_3->configfile ) {
4866 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4868 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4869 DEBUG(10,("deleting configfile [%s]\n", s));
4870 unlink_internals(conn, 0, file, False);
4874 if ( *info_3->datafile ) {
4875 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4877 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4878 DEBUG(10,("deleting datafile [%s]\n", s));
4879 unlink_internals(conn, 0, file, False);
4883 if ( *info_3->helpfile ) {
4884 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4886 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4887 DEBUG(10,("deleting helpfile [%s]\n", s));
4888 unlink_internals(conn, 0, file, False);
4892 /* check if we are done removing files */
4894 if ( info_3->dependentfiles ) {
4895 while ( info_3->dependentfiles[i][0] ) {
4898 /* bypass the "\print$" portion of the path */
4900 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4902 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4903 DEBUG(10,("deleting dependent file [%s]\n", file));
4904 unlink_internals(conn, 0, file, False);
4916 /****************************************************************************
4917 Remove a printer driver from the TDB. This assumes that the the driver was
4918 previously looked up.
4919 ***************************************************************************/
4921 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4922 uint32 version, BOOL delete_files )
4926 TDB_DATA kbuf, dbuf;
4927 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4929 /* delete the tdb data first */
4931 arch = get_short_archi(info_3->environment);
4933 return WERR_UNKNOWN_PRINTER_DRIVER;
4935 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4936 arch, version, info_3->name);
4938 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4939 key, delete_files ? "TRUE" : "FALSE" ));
4941 ctr.info_3 = info_3;
4942 dump_a_printer_driver( ctr, 3 );
4945 kbuf.dsize=strlen(key)+1;
4947 /* check if the driver actually exists for this environment */
4949 dbuf = tdb_fetch( tdb_drivers, kbuf );
4951 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4952 return WERR_UNKNOWN_PRINTER_DRIVER;
4955 SAFE_FREE( dbuf.dptr );
4957 /* ok... the driver exists so the delete should return success */
4959 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4960 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4961 return WERR_ACCESS_DENIED;
4965 * now delete any associated files if delete_files == True
4966 * even if this part failes, we return succes because the
4967 * driver doesn not exist any more
4971 delete_driver_files( info_3, user );
4974 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4979 /****************************************************************************
4980 Store a security desc for a printer.
4981 ****************************************************************************/
4983 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4985 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4986 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4988 TALLOC_CTX *mem_ctx = NULL;
4992 mem_ctx = talloc_init("nt_printing_setsec");
4993 if (mem_ctx == NULL)
4996 /* The old owner and group sids of the security descriptor are not
4997 present when new ACEs are added or removed by changing printer
4998 permissions through NT. If they are NULL in the new security
4999 descriptor then copy them over from the old one. */
5001 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
5002 DOM_SID *owner_sid, *group_sid;
5003 SEC_ACL *dacl, *sacl;
5004 SEC_DESC *psd = NULL;
5007 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5008 status = WERR_NOMEM;
5012 /* Pick out correct owner and group sids */
5014 owner_sid = secdesc_ctr->sec->owner_sid ?
5015 secdesc_ctr->sec->owner_sid :
5016 old_secdesc_ctr->sec->owner_sid;
5018 group_sid = secdesc_ctr->sec->grp_sid ?
5019 secdesc_ctr->sec->grp_sid :
5020 old_secdesc_ctr->sec->grp_sid;
5022 dacl = secdesc_ctr->sec->dacl ?
5023 secdesc_ctr->sec->dacl :
5024 old_secdesc_ctr->sec->dacl;
5026 sacl = secdesc_ctr->sec->sacl ?
5027 secdesc_ctr->sec->sacl :
5028 old_secdesc_ctr->sec->sacl;
5030 /* Make a deep copy of the security descriptor */
5032 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
5033 owner_sid, group_sid,
5039 status = WERR_NOMEM;
5043 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5046 if (!new_secdesc_ctr) {
5047 new_secdesc_ctr = secdesc_ctr;
5050 /* Store the security descriptor in a tdb */
5052 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
5053 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5055 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5057 status = WERR_BADFUNC;
5061 key = make_printers_secdesc_tdbkey( sharename );
5063 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
5066 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5067 status = WERR_BADFUNC;
5070 /* Free malloc'ed memory */
5076 talloc_destroy(mem_ctx);
5080 /****************************************************************************
5081 Construct a default security descriptor buffer for a printer.
5082 ****************************************************************************/
5084 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5086 SEC_ACE ace[5]; /* max number of ace entries */
5089 SEC_ACL *psa = NULL;
5090 SEC_DESC_BUF *sdb = NULL;
5091 SEC_DESC *psd = NULL;
5095 /* Create an ACE where Everyone is allowed to print */
5097 init_sec_access(&sa, PRINTER_ACE_PRINT);
5098 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5099 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5101 /* Add the domain admins group if we are a DC */
5104 DOM_SID domadmins_sid;
5106 sid_copy(&domadmins_sid, get_global_sam_sid());
5107 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5109 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5110 init_sec_ace(&ace[i++], &domadmins_sid,
5111 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5112 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5113 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5114 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5116 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5117 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5119 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5120 init_sec_ace(&ace[i++], &adm_sid,
5121 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5122 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5123 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5124 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5127 /* add BUILTIN\Administrators as FULL CONTROL */
5129 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5130 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5131 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5132 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5133 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5134 SEC_ACE_TYPE_ACCESS_ALLOWED,
5135 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5137 /* Make the security descriptor owned by the BUILTIN\Administrators */
5139 /* The ACL revision number in rpc_secdesc.h differs from the one
5140 created by NT when setting ACE entries in printer
5141 descriptors. NT4 complains about the property being edited by a
5144 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5145 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5146 &global_sid_Builtin_Administrators,
5147 &global_sid_Builtin_Administrators,
5148 NULL, psa, &sd_size);
5152 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5156 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5158 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5159 (unsigned int)sd_size));
5164 /****************************************************************************
5165 Get a security desc for a printer.
5166 ****************************************************************************/
5168 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5174 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5175 sharename = temp + 1;
5180 /* Fetch security descriptor from tdb */
5182 key = make_printers_secdesc_tdbkey( sharename );
5184 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5185 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5189 DEBUG(4,("using default secdesc for %s\n", sharename));
5191 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5195 /* Save default security descriptor for later */
5197 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5198 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5200 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5201 tdb_prs_store(tdb_printers, key, &ps);
5211 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5212 this security descriptor has been created when winbindd was
5213 down. Take ownership of security descriptor. */
5215 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5218 /* Change sd owner to workgroup administrator */
5220 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5221 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5222 SEC_DESC *psd = NULL;
5227 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5229 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5231 (*secdesc_ctr)->sec->grp_sid,
5232 (*secdesc_ctr)->sec->sacl,
5233 (*secdesc_ctr)->sec->dacl,
5240 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5241 if (!new_secdesc_ctr) {
5245 /* Swap with other one */
5247 *secdesc_ctr = new_secdesc_ctr;
5251 nt_printing_setsec(sharename, *secdesc_ctr);
5255 if (DEBUGLEVEL >= 10) {
5256 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5259 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5260 sharename, the_acl->num_aces));
5262 for (i = 0; i < the_acl->num_aces; i++) {
5265 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5267 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5268 the_acl->ace[i].type, the_acl->ace[i].flags,
5269 the_acl->ace[i].info.mask));
5278 1: level not implemented
5279 2: file doesn't exist
5280 3: can't allocate memory
5281 4: can't free memory
5282 5: non existant struct
5286 A printer and a printer driver are 2 different things.
5287 NT manages them separatelly, Samba does the same.
5288 Why ? Simply because it's easier and it makes sense !
5290 Now explanation: You have 3 printers behind your samba server,
5291 2 of them are the same make and model (laser A and B). But laser B
5292 has an 3000 sheet feeder and laser A doesn't such an option.
5293 Your third printer is an old dot-matrix model for the accounting :-).
5295 If the /usr/local/samba/lib directory (default dir), you will have
5296 5 files to describe all of this.
5298 3 files for the printers (1 by printer):
5301 NTprinter_accounting
5302 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5303 NTdriver_printer model X
5304 NTdriver_printer model Y
5306 jfm: I should use this comment for the text file to explain
5307 same thing for the forms BTW.
5308 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5312 /* Convert generic access rights to printer object specific access rights.
5313 It turns out that NT4 security descriptors use generic access rights and
5314 NT5 the object specific ones. */
5316 void map_printer_permissions(SEC_DESC *sd)
5320 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5321 se_map_generic(&sd->dacl->ace[i].info.mask,
5322 &printer_generic_mapping);
5326 /****************************************************************************
5327 Check a user has permissions to perform the given operation. We use the
5328 permission constants defined in include/rpc_spoolss.h to check the various
5329 actions we perform when checking printer access.
5331 PRINTER_ACCESS_ADMINISTER:
5332 print_queue_pause, print_queue_resume, update_printer_sec,
5333 update_printer, spoolss_addprinterex_level_2,
5334 _spoolss_setprinterdata
5339 JOB_ACCESS_ADMINISTER:
5340 print_job_delete, print_job_pause, print_job_resume,
5343 Try access control in the following order (for performance reasons):
5344 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5345 2) check security descriptor (bit comparisons in memory)
5346 3) "printer admins" (may result in numerous calls to winbind)
5348 ****************************************************************************/
5349 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5351 SEC_DESC_BUF *secdesc = NULL;
5352 uint32 access_granted;
5356 TALLOC_CTX *mem_ctx = NULL;
5357 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5359 /* If user is NULL then use the current_user structure */
5362 user = ¤t_user;
5364 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5366 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5370 /* Get printer name */
5372 pname = PRINTERNAME(snum);
5374 if (!pname || !*pname) {
5379 /* Get printer security descriptor */
5381 if(!(mem_ctx = talloc_init("print_access_check"))) {
5386 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5387 talloc_destroy(mem_ctx);
5392 if (access_type == JOB_ACCESS_ADMINISTER) {
5393 SEC_DESC_BUF *parent_secdesc = secdesc;
5395 /* Create a child security descriptor to check permissions
5396 against. This is because print jobs are child objects
5397 objects of a printer. */
5399 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5402 talloc_destroy(mem_ctx);
5407 /* Now this is the bit that really confuses me. The access
5408 type needs to be changed from JOB_ACCESS_ADMINISTER to
5409 PRINTER_ACCESS_ADMINISTER for this to work. Something
5410 to do with the child (job) object becoming like a
5413 access_type = PRINTER_ACCESS_ADMINISTER;
5418 map_printer_permissions(secdesc->sec);
5420 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5421 &access_granted, &status);
5423 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5425 /* see if we need to try the printer admin list */
5427 if ((access_granted == 0) &&
5428 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5429 user->nt_user_token,
5430 lp_printer_admin(snum)))) {
5431 talloc_destroy(mem_ctx);
5435 talloc_destroy(mem_ctx);
5444 /****************************************************************************
5445 Check the time parameters allow a print operation.
5446 *****************************************************************************/
5448 BOOL print_time_access_check(const char *servicename)
5450 NT_PRINTER_INFO_LEVEL *printer = NULL;
5452 time_t now = time(NULL);
5456 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5459 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5463 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5465 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5468 free_a_printer(&printer, 2);
5476 /****************************************************************************
5477 Fill in the servername sent in the _spoolss_open_printer_ex() call
5478 ****************************************************************************/
5480 char* get_server_name( Printer_entry *printer )
5482 return printer->servername;