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)
352 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
355 /* upgrade the security descriptor */
359 prs_init( &ps, 0, ctx, UNMARSHALL );
360 prs_give_memory( &ps, data.dptr, data.dsize, True );
362 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
363 /* delete bad entries */
364 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
365 tdb_delete( tdb_printers, key );
371 /* is this even valid? */
376 /* update access masks */
378 for ( i=0; i<sec->dacl->num_aces; i++ ) {
379 switch ( sec->dacl->ace[i].info.mask ) {
380 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
381 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
384 case GENERIC_ALL_ACCESS:
385 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
388 case READ_CONTROL_ACCESS:
389 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
391 default: /* no change */
396 /* create a new SEC_DESC with the appropriate owner and group SIDs */
398 string_to_sid(&sid, "S-1-5-32-544" );
399 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
401 NULL, NULL, &size_new_sec );
402 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
404 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
405 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
411 sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
412 prs_init(&ps, sd_size, ctx, MARSHALL);
414 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
415 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
419 data.dptr = prs_data_p( &ps );
420 data.dsize = sd_size;
422 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
426 /* 0 to continue and non-zero to stop traversal */
428 return (result == -1);
431 /*******************************************************************
432 *******************************************************************/
434 static BOOL upgrade_to_version_4(void)
439 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
441 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
444 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
446 talloc_destroy( ctx );
448 return ( result != -1 );
451 /*******************************************************************
452 Fix an issue with security descriptors. Printer sec_desc must
453 use more than the generic bits that were previously used
454 in <= 3.0.14a. They must also have a owner and group SID assigned.
455 Otherwise, any printers than have been migrated to a Windows
456 host using printmig.exe will not be accessible.
457 *******************************************************************/
459 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
460 TDB_DATA data, void *state )
464 if (!data.dptr || data.dsize == 0)
467 /* upgrade printer records and security descriptors */
469 if ( strncmp( key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470 new_key = make_printer_tdbkey( key.dptr+strlen(PRINTERS_PREFIX) );
472 else if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473 new_key.dptr = make_printers_secdesc_tdbkey( key.dptr+strlen(SECDESC_PREFIX) );
474 new_key.dsize = strlen( new_key.dptr ) + 1;
477 /* ignore this record */
481 /* delete the original record and store under the normalized key */
483 if ( tdb_delete( the_tdb, key ) != 0 ) {
484 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
489 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
490 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
498 /*******************************************************************
499 *******************************************************************/
501 static BOOL upgrade_to_version_5(void)
506 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
508 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
511 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
513 talloc_destroy( ctx );
515 return ( result != -1 );
518 /****************************************************************************
519 Open the NT printing tdbs. Done once before fork().
520 ****************************************************************************/
522 BOOL nt_printing_init(void)
524 const char *vstring = "INFO/version";
528 if ( tdb_drivers && tdb_printers && tdb_forms )
532 tdb_close(tdb_drivers);
533 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
535 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
536 lock_path("ntdrivers.tdb"), strerror(errno) ));
541 tdb_close(tdb_printers);
542 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
544 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
545 lock_path("ntprinters.tdb"), strerror(errno) ));
550 tdb_close(tdb_forms);
551 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
553 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
554 lock_path("ntforms.tdb"), strerror(errno) ));
558 /* handle a Samba upgrade */
560 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
562 DEBUG(10, ("Fresh database\n"));
563 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
564 vers_id = NTDRIVERS_DATABASE_VERSION_5;
567 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
569 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
570 if (!upgrade_to_version_3())
572 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
573 vers_id = NTDRIVERS_DATABASE_VERSION_3;
576 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
577 /* Written on a bigendian machine with old fetch_int code. Save as le. */
578 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
579 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
580 vers_id = NTDRIVERS_DATABASE_VERSION_3;
583 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
584 if ( !upgrade_to_version_4() )
586 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
587 vers_id = NTDRIVERS_DATABASE_VERSION_4;
590 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
591 if ( !upgrade_to_version_5() )
593 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
594 vers_id = NTDRIVERS_DATABASE_VERSION_5;
598 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
599 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
604 update_c_setprinter(True);
607 * register callback to handle updating printers as new
608 * drivers are installed
611 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
614 * register callback to handle updating printer data
615 * when a driver is initialized
618 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
620 /* of course, none of the message callbacks matter if you don't
621 tell messages.c that you interested in receiving PRINT_GENERAL
622 msgs. This is done in claim_connection() */
625 if ( lp_security() == SEC_ADS ) {
626 win_rc = check_published_printers();
627 if (!W_ERROR_IS_OK(win_rc))
628 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
634 /*******************************************************************
635 Function to allow filename parsing "the old way".
636 ********************************************************************/
638 static BOOL driver_unix_convert(char *name,connection_struct *conn,
639 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
642 unix_clean_name(name);
643 trim_string(name,"/","/");
644 return unix_convert(name, conn, saved_last_component, bad_path, pst);
647 /*******************************************************************
648 tdb traversal function for counting printers.
649 ********************************************************************/
651 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
652 TDB_DATA data, void *context)
654 int *printer_count = (int*)context;
656 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
658 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
664 /*******************************************************************
665 Update the spooler global c_setprinter. This variable is initialized
666 when the parent smbd starts with the number of existing printers. It
667 is monotonically increased by the current number of printers *after*
668 each add or delete printer RPC. Only Microsoft knows why... JRR020119
669 ********************************************************************/
671 uint32 update_c_setprinter(BOOL initialize)
674 int32 printer_count = 0;
676 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
678 /* Traverse the tdb, counting the printers */
679 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
681 /* If initializing, set c_setprinter to current printers count
682 * otherwise, bump it by the current printer count
685 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
687 c_setprinter = printer_count;
689 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
690 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
692 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
694 return (uint32)c_setprinter;
697 /*******************************************************************
698 Get the spooler global c_setprinter, accounting for initialization.
699 ********************************************************************/
701 uint32 get_c_setprinter(void)
703 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
705 if (c_setprinter == (int32)-1)
706 c_setprinter = update_c_setprinter(True);
708 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
710 return (uint32)c_setprinter;
713 /****************************************************************************
714 Get builtin form struct list.
715 ****************************************************************************/
717 int get_builtin_ntforms(nt_forms_struct **list)
719 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
720 return sizeof(default_forms) / sizeof(default_forms[0]);
723 /****************************************************************************
724 get a builtin form struct
725 ****************************************************************************/
727 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
731 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
732 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
733 count = sizeof(default_forms) / sizeof(default_forms[0]);
734 for (i=0;i<count;i++) {
735 if (strequal(form_name,default_forms[i].name)) {
736 DEBUGADD(6,("Found builtin form %s \n", form_name));
737 memcpy(form,&default_forms[i],sizeof(*form));
745 /****************************************************************************
746 get a form struct list.
747 ****************************************************************************/
749 int get_ntforms(nt_forms_struct **list)
751 TDB_DATA kbuf, newkey, dbuf;
752 nt_forms_struct form;
759 for (kbuf = tdb_firstkey(tdb_forms);
761 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
763 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
766 dbuf = tdb_fetch(tdb_forms, kbuf);
770 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
771 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
772 &i, &form.flag, &form.width, &form.length, &form.left,
773 &form.top, &form.right, &form.bottom);
774 SAFE_FREE(dbuf.dptr);
775 if (ret != dbuf.dsize)
778 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
780 DEBUG(0,("get_ntforms: Realloc fail.\n"));
791 /****************************************************************************
792 write a form struct list
793 ****************************************************************************/
794 int write_ntforms(nt_forms_struct **list, int number)
801 for (i=0;i<number;i++) {
802 /* save index, so list is rebuilt in correct order */
803 len = tdb_pack(buf, sizeof(buf), "dddddddd",
804 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
805 (*list)[i].left, (*list)[i].top, (*list)[i].right,
807 if (len > sizeof(buf)) break;
808 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
809 kbuf.dsize = strlen(key)+1;
813 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
819 /****************************************************************************
820 add a form struct at the end of the list
821 ****************************************************************************/
822 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
829 * NT tries to add forms even when
830 * they are already in the base
831 * only update the values if already present
836 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
837 for (n=0; n<*count; n++) {
838 if ( strequal((*list)[n].name, form_name) ) {
845 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
846 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
849 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
853 (*list)[n].flag=form->flags;
854 (*list)[n].width=form->size_x;
855 (*list)[n].length=form->size_y;
856 (*list)[n].left=form->left;
857 (*list)[n].top=form->top;
858 (*list)[n].right=form->right;
859 (*list)[n].bottom=form->bottom;
861 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
862 update ? "updated" : "added", form_name));
867 /****************************************************************************
868 Delete a named form struct.
869 ****************************************************************************/
871 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
880 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
882 for (n=0; n<*count; n++) {
883 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
884 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
890 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
891 *ret = WERR_INVALID_PARAM;
895 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
896 kbuf.dsize = strlen(key)+1;
898 if (tdb_delete(tdb_forms, kbuf) != 0) {
906 /****************************************************************************
907 Update a form struct.
908 ****************************************************************************/
910 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
914 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
916 DEBUG(106, ("[%s]\n", form_name));
917 for (n=0; n<count; n++) {
918 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
919 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
923 if (n==count) return;
925 (*list)[n].flag=form->flags;
926 (*list)[n].width=form->size_x;
927 (*list)[n].length=form->size_y;
928 (*list)[n].left=form->left;
929 (*list)[n].top=form->top;
930 (*list)[n].right=form->right;
931 (*list)[n].bottom=form->bottom;
934 /****************************************************************************
935 Get the nt drivers list.
936 Traverse the database and look-up the matching names.
937 ****************************************************************************/
938 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
941 const char *short_archi;
943 TDB_DATA kbuf, newkey;
945 short_archi = get_short_archi(architecture);
946 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
948 for (kbuf = tdb_firstkey(tdb_drivers);
950 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
952 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
955 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
956 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
960 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
967 /****************************************************************************
968 function to do the mapping between the long architecture name and
970 ****************************************************************************/
971 const char *get_short_archi(const char *long_archi)
975 DEBUG(107,("Getting architecture dependant directory\n"));
978 } while ( (archi_table[i].long_archi!=NULL ) &&
979 StrCaseCmp(long_archi, archi_table[i].long_archi) );
981 if (archi_table[i].long_archi==NULL) {
982 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
986 /* this might be client code - but shouldn't this be an fstrcpy etc? */
989 DEBUGADD(108,("index: [%d]\n", i));
990 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
991 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
993 return archi_table[i].short_archi;
996 /****************************************************************************
997 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
998 There are two case to be covered here: PE (Portable Executable) and NE (New
999 Executable) files. Both files support the same INFO structure, but PE files
1000 store the signature in unicode, and NE files store it as !unicode.
1001 returns -1 on error, 1 on version info found, and 0 on no version info found.
1002 ****************************************************************************/
1004 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1010 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
1011 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1012 fname, PE_HEADER_SIZE));
1016 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1017 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1018 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1019 fname, (unsigned long)byte_count));
1020 goto no_version_info;
1023 /* Is this really a DOS header? */
1024 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1025 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1026 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1027 goto no_version_info;
1030 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1031 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1032 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1034 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1035 goto no_version_info;
1038 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
1039 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1040 fname, (unsigned long)byte_count));
1041 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1042 goto no_version_info;
1045 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1046 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1047 unsigned int num_sections;
1048 unsigned int section_table_bytes;
1050 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
1051 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1052 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
1053 /* At this point, we assume the file is in error. It still could be somthing
1054 * else besides a PE file, but it unlikely at this point.
1059 /* get the section table */
1060 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1061 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1062 if (section_table_bytes == 0)
1066 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
1067 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1068 fname, section_table_bytes));
1072 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1073 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1074 fname, (unsigned long)byte_count));
1078 /* Iterate the section table looking for the resource section ".rsrc" */
1079 for (i = 0; i < num_sections; i++) {
1080 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1082 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1083 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1084 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1086 if (section_bytes == 0)
1090 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
1091 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1092 fname, section_bytes));
1096 /* Seek to the start of the .rsrc section info */
1097 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1098 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1103 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1104 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1105 fname, (unsigned long)byte_count));
1109 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1112 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1113 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1114 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1115 /* Align to next long address */
1116 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1118 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1119 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1120 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1122 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1123 fname, *major, *minor,
1124 (*major>>16)&0xffff, *major&0xffff,
1125 (*minor>>16)&0xffff, *minor&0xffff));
1134 /* Version info not found, fall back to origin date/time */
1135 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1139 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1140 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1141 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1142 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1143 /* At this point, we assume the file is in error. It still could be somthing
1144 * else besides a NE file, but it unlikely at this point. */
1148 /* Allocate a bit more space to speed up things */
1150 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1151 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1152 fname, PE_HEADER_SIZE));
1156 /* This is a HACK! I got tired of trying to sort through the messy
1157 * 'NE' file format. If anyone wants to clean this up please have at
1158 * it, but this works. 'NE' files will eventually fade away. JRR */
1159 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1160 /* Cover case that should not occur in a well formed 'NE' .dll file */
1161 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1163 for(i=0; i<byte_count; i++) {
1164 /* Fast skip past data that can't possibly match */
1165 if (buf[i] != 'V') continue;
1167 /* Potential match data crosses buf boundry, move it to beginning
1168 * of buf, and fill the buf with as much as it will hold. */
1169 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1172 memcpy(buf, &buf[i], byte_count-i);
1173 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1174 (byte_count-i))) < 0) {
1176 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1181 byte_count = bc + (byte_count - i);
1182 if (byte_count<VS_VERSION_INFO_SIZE) break;
1187 /* Check that the full signature string and the magic number that
1188 * follows exist (not a perfect solution, but the chances that this
1189 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1190 * twice, as it is simpler to read the code. */
1191 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1192 /* Compute skip alignment to next long address */
1193 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1194 sizeof(VS_SIGNATURE)) & 3;
1195 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1197 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1198 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1199 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1200 fname, *major, *minor,
1201 (*major>>16)&0xffff, *major&0xffff,
1202 (*minor>>16)&0xffff, *minor&0xffff));
1209 /* Version info not found, fall back to origin date/time */
1210 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1215 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1216 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1217 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1228 /****************************************************************************
1229 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1230 share one or more files. During the MS installation process files are checked
1231 to insure that only a newer version of a shared file is installed over an
1232 older version. There are several possibilities for this comparison. If there
1233 is no previous version, the new one is newer (obviously). If either file is
1234 missing the version info structure, compare the creation date (on Unix use
1235 the modification date). Otherwise chose the numerically larger version number.
1236 ****************************************************************************/
1238 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1240 BOOL use_version = True;
1245 time_t new_create_time;
1249 time_t old_create_time;
1251 files_struct *fsp = NULL;
1253 SMB_STRUCT_STAT stat_buf;
1256 SET_STAT_INVALID(st);
1257 SET_STAT_INVALID(stat_buf);
1258 new_create_time = (time_t)0;
1259 old_create_time = (time_t)0;
1261 /* Get file version info (if available) for previous file (if it exists) */
1262 pstrcpy(filepath, old_file);
1264 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1266 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1268 FILE_SHARE_READ|FILE_SHARE_WRITE,
1271 FILE_ATTRIBUTE_NORMAL,
1276 /* Old file not found, so by definition new file is in fact newer */
1277 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1282 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1288 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1290 use_version = False;
1291 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1292 old_create_time = st.st_mtime;
1293 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1296 close_file(fsp, NORMAL_CLOSE);
1298 /* Get file version info (if available) for new file */
1299 pstrcpy(filepath, new_file);
1300 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1302 fsp = open_file_ntcreate(conn, filepath, &stat_buf,
1304 FILE_SHARE_READ|FILE_SHARE_WRITE,
1307 FILE_ATTRIBUTE_NORMAL,
1312 /* New file not found, this shouldn't occur if the caller did its job */
1313 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1318 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1324 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1326 use_version = False;
1327 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1328 new_create_time = st.st_mtime;
1329 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1332 close_file(fsp, NORMAL_CLOSE);
1334 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1335 /* Compare versions and choose the larger version number */
1336 if (new_major > old_major ||
1337 (new_major == old_major && new_minor > old_minor)) {
1339 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1343 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1348 /* Compare modification time/dates and choose the newest time/date */
1349 if (new_create_time > old_create_time) {
1350 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1354 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1361 close_file(fsp, NORMAL_CLOSE);
1365 /****************************************************************************
1366 Determine the correct cVersion associated with an architecture and driver
1367 ****************************************************************************/
1368 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1369 struct current_user *user, WERROR *perr)
1376 files_struct *fsp = NULL;
1379 connection_struct *conn;
1381 SET_STAT_INVALID(st);
1383 *perr = WERR_INVALID_PARAM;
1385 /* If architecture is Windows 95/98/ME, the version is always 0. */
1386 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1387 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1392 /* If architecture is Windows x64, the version is always 3. */
1393 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1394 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1400 * Connect to the print$ share under the same account as the user connected
1401 * to the rpc pipe. Note we must still be root to do this.
1404 /* Null password is ok - we are already an authenticated user... */
1405 null_pw = data_blob(NULL, 0);
1406 fstrcpy(res_type, "A:");
1408 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1412 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1413 *perr = ntstatus_to_werror(nt_status);
1417 /* We are temporarily becoming the connection user. */
1418 if (!become_user(conn, user->vuid)) {
1419 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1420 *perr = WERR_ACCESS_DENIED;
1424 /* Open the driver file (Portable Executable format) and determine the
1425 * deriver the cversion. */
1426 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1428 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1430 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1431 *perr = WERR_BADFILE;
1435 fsp = open_file_ntcreate(conn, driverpath, &st,
1437 FILE_SHARE_READ|FILE_SHARE_WRITE,
1440 FILE_ATTRIBUTE_NORMAL,
1445 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1446 driverpath, errno));
1447 *perr = WERR_ACCESS_DENIED;
1452 int ret = get_file_version(fsp, driverpath, &major, &minor);
1453 if (ret == -1) goto error_exit;
1456 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1461 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1462 * for more details. Version in this case is not just the version of the
1463 * file, but the version in the sense of kernal mode (2) vs. user mode
1464 * (3) drivers. Other bits of the version fields are the version info.
1467 cversion = major & 0x0000ffff;
1469 case 2: /* WinNT drivers */
1470 case 3: /* Win2K drivers */
1474 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1475 driverpath, cversion));
1479 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1480 driverpath, major, minor));
1483 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1484 driverpath, cversion));
1486 close_file(fsp, NORMAL_CLOSE);
1487 close_cnum(conn, user->vuid);
1496 close_file(fsp, NORMAL_CLOSE);
1498 close_cnum(conn, user->vuid);
1503 /****************************************************************************
1504 ****************************************************************************/
1505 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1506 struct current_user *user)
1508 const char *architecture;
1514 /* clean up the driver name.
1515 * we can get .\driver.dll
1516 * or worse c:\windows\system\driver.dll !
1518 /* using an intermediate string to not have overlaping memcpy()'s */
1519 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1520 fstrcpy(new_name, p+1);
1521 fstrcpy(driver->driverpath, new_name);
1524 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1525 fstrcpy(new_name, p+1);
1526 fstrcpy(driver->datafile, new_name);
1529 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1530 fstrcpy(new_name, p+1);
1531 fstrcpy(driver->configfile, new_name);
1534 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1535 fstrcpy(new_name, p+1);
1536 fstrcpy(driver->helpfile, new_name);
1539 if (driver->dependentfiles) {
1540 for (i=0; *driver->dependentfiles[i]; i++) {
1541 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1542 fstrcpy(new_name, p+1);
1543 fstrcpy(driver->dependentfiles[i], new_name);
1548 architecture = get_short_archi(driver->environment);
1550 /* jfm:7/16/2000 the client always sends the cversion=0.
1551 * The server should check which version the driver is by reading
1552 * the PE header of driver->driverpath.
1554 * For Windows 95/98 the version is 0 (so the value sent is correct)
1555 * For Windows NT (the architecture doesn't matter)
1556 * NT 3.1: cversion=0
1557 * NT 3.5/3.51: cversion=1
1561 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1567 /****************************************************************************
1568 ****************************************************************************/
1569 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1571 const char *architecture;
1577 /* clean up the driver name.
1578 * we can get .\driver.dll
1579 * or worse c:\windows\system\driver.dll !
1581 /* using an intermediate string to not have overlaping memcpy()'s */
1582 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1583 fstrcpy(new_name, p+1);
1584 fstrcpy(driver->driverpath, new_name);
1587 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1588 fstrcpy(new_name, p+1);
1589 fstrcpy(driver->datafile, new_name);
1592 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1593 fstrcpy(new_name, p+1);
1594 fstrcpy(driver->configfile, new_name);
1597 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1598 fstrcpy(new_name, p+1);
1599 fstrcpy(driver->helpfile, new_name);
1602 if (driver->dependentfiles) {
1603 for (i=0; *driver->dependentfiles[i]; i++) {
1604 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1605 fstrcpy(new_name, p+1);
1606 fstrcpy(driver->dependentfiles[i], new_name);
1611 architecture = get_short_archi(driver->environment);
1613 /* jfm:7/16/2000 the client always sends the cversion=0.
1614 * The server should check which version the driver is by reading
1615 * the PE header of driver->driverpath.
1617 * For Windows 95/98 the version is 0 (so the value sent is correct)
1618 * For Windows NT (the architecture doesn't matter)
1619 * NT 3.1: cversion=0
1620 * NT 3.5/3.51: cversion=1
1625 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1631 /****************************************************************************
1632 ****************************************************************************/
1633 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1634 uint32 level, struct current_user *user)
1639 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1640 driver=driver_abstract.info_3;
1641 return clean_up_driver_struct_level_3(driver, user);
1645 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1646 driver=driver_abstract.info_6;
1647 return clean_up_driver_struct_level_6(driver, user);
1650 return WERR_INVALID_PARAM;
1654 /****************************************************************************
1655 This function sucks and should be replaced. JRA.
1656 ****************************************************************************/
1658 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1660 dst->cversion = src->version;
1662 fstrcpy( dst->name, src->name);
1663 fstrcpy( dst->environment, src->environment);
1664 fstrcpy( dst->driverpath, src->driverpath);
1665 fstrcpy( dst->datafile, src->datafile);
1666 fstrcpy( dst->configfile, src->configfile);
1667 fstrcpy( dst->helpfile, src->helpfile);
1668 fstrcpy( dst->monitorname, src->monitorname);
1669 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1670 dst->dependentfiles = src->dependentfiles;
1673 #if 0 /* Debugging function */
1675 static char* ffmt(unsigned char *c){
1677 static char ffmt_str[17];
1679 for (i=0; i<16; i++) {
1680 if ((c[i] < ' ') || (c[i] > '~'))
1691 /****************************************************************************
1692 ****************************************************************************/
1693 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1694 struct current_user *user, WERROR *perr)
1696 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1697 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1698 const char *architecture;
1703 connection_struct *conn;
1714 memset(inbuf, '\0', sizeof(inbuf));
1715 memset(outbuf, '\0', sizeof(outbuf));
1719 driver=driver_abstract.info_3;
1720 else if (level==6) {
1721 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1722 driver = &converted_driver;
1724 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1725 return WERR_UNKNOWN_LEVEL;
1728 architecture = get_short_archi(driver->environment);
1731 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1732 * Note we must be root to do this.
1735 null_pw = data_blob(NULL, 0);
1736 fstrcpy(res_type, "A:");
1738 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1742 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1743 *perr = ntstatus_to_werror(nt_status);
1744 return WERR_NO_SUCH_SHARE;
1748 * Save who we are - we are temporarily becoming the connection user.
1751 if (!become_user(conn, conn->vuid)) {
1752 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1753 return WERR_ACCESS_DENIED;
1757 * make the directories version and version\driver_name
1758 * under the architecture directory.
1760 DEBUG(5,("Creating first directory\n"));
1761 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1762 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1763 mkdir_internal(conn, new_dir, bad_path);
1765 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1766 * listed for this driver which has already been moved, skip it (note:
1767 * drivers may list the same file name several times. Then check if the
1768 * file already exists in archi\cversion\, if so, check that the version
1769 * info (or time stamps if version info is unavailable) is newer (or the
1770 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1771 * Otherwise, delete the file.
1773 * If a file is not moved to archi\cversion\ because of an error, all the
1774 * rest of the 'unmoved' driver files are removed from archi\. If one or
1775 * more of the driver's files was already moved to archi\cversion\, it
1776 * potentially leaves the driver in a partially updated state. Version
1777 * trauma will most likely occur if an client attempts to use any printer
1778 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1779 * done is appropriate... later JRR
1782 DEBUG(5,("Moving files now !\n"));
1784 if (driver->driverpath && strlen(driver->driverpath)) {
1785 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1786 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1787 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1788 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1789 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1790 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1791 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1792 new_name, old_name));
1793 *perr = WERR_ACCESS_DENIED;
1799 if (driver->datafile && strlen(driver->datafile)) {
1800 if (!strequal(driver->datafile, driver->driverpath)) {
1801 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1802 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1803 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1804 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1805 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1806 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1807 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1808 new_name, old_name));
1809 *perr = WERR_ACCESS_DENIED;
1816 if (driver->configfile && strlen(driver->configfile)) {
1817 if (!strequal(driver->configfile, driver->driverpath) &&
1818 !strequal(driver->configfile, driver->datafile)) {
1819 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1820 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1821 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1822 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1823 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1824 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1825 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1826 new_name, old_name));
1827 *perr = WERR_ACCESS_DENIED;
1834 if (driver->helpfile && strlen(driver->helpfile)) {
1835 if (!strequal(driver->helpfile, driver->driverpath) &&
1836 !strequal(driver->helpfile, driver->datafile) &&
1837 !strequal(driver->helpfile, driver->configfile)) {
1838 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1839 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1840 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1841 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1842 if ( !copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
1843 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1844 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1845 new_name, old_name));
1846 *perr = WERR_ACCESS_DENIED;
1853 if (driver->dependentfiles) {
1854 for (i=0; *driver->dependentfiles[i]; i++) {
1855 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1856 !strequal(driver->dependentfiles[i], driver->datafile) &&
1857 !strequal(driver->dependentfiles[i], driver->configfile) &&
1858 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1860 for (j=0; j < i; j++) {
1861 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1866 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1867 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1868 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1869 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1870 if ( !copy_file(new_name, old_name, conn,
1871 OPENX_FILE_EXISTS_TRUNCATE|
1872 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1873 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1874 new_name, old_name));
1875 *perr = WERR_ACCESS_DENIED;
1884 close_cnum(conn, user->vuid);
1887 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1890 /****************************************************************************
1891 ****************************************************************************/
1892 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1895 const char *architecture;
1901 TDB_DATA kbuf, dbuf;
1903 architecture = get_short_archi(driver->environment);
1905 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1906 * \\server is added in the rpc server layer.
1907 * It does make sense to NOT store the server's name in the printer TDB.
1910 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1912 /* .inf files do not always list a file for each of the four standard files.
1913 * Don't prepend a path to a null filename, or client claims:
1914 * "The server on which the printer resides does not have a suitable
1915 * <printer driver name> printer driver installed. Click OK if you
1916 * wish to install the driver on your local machine."
1918 if (strlen(driver->driverpath)) {
1919 fstrcpy(temp_name, driver->driverpath);
1920 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1923 if (strlen(driver->datafile)) {
1924 fstrcpy(temp_name, driver->datafile);
1925 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1928 if (strlen(driver->configfile)) {
1929 fstrcpy(temp_name, driver->configfile);
1930 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1933 if (strlen(driver->helpfile)) {
1934 fstrcpy(temp_name, driver->helpfile);
1935 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1938 if (driver->dependentfiles) {
1939 for (i=0; *driver->dependentfiles[i]; i++) {
1940 fstrcpy(temp_name, driver->dependentfiles[i]);
1941 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1945 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1947 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1954 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1957 driver->environment,
1962 driver->monitorname,
1963 driver->defaultdatatype);
1965 if (driver->dependentfiles) {
1966 for (i=0; *driver->dependentfiles[i]; i++) {
1967 len += tdb_pack(buf+len, buflen-len, "f",
1968 driver->dependentfiles[i]);
1972 if (len != buflen) {
1973 buf = (char *)SMB_REALLOC(buf, len);
1975 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1985 kbuf.dsize = strlen(key)+1;
1989 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1993 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1999 /****************************************************************************
2000 ****************************************************************************/
2001 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2003 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2006 info3.cversion = driver->version;
2007 fstrcpy(info3.name,driver->name);
2008 fstrcpy(info3.environment,driver->environment);
2009 fstrcpy(info3.driverpath,driver->driverpath);
2010 fstrcpy(info3.datafile,driver->datafile);
2011 fstrcpy(info3.configfile,driver->configfile);
2012 fstrcpy(info3.helpfile,driver->helpfile);
2013 fstrcpy(info3.monitorname,driver->monitorname);
2014 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2015 info3.dependentfiles = driver->dependentfiles;
2017 return add_a_printer_driver_3(&info3);
2021 /****************************************************************************
2022 ****************************************************************************/
2023 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2025 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2029 fstrcpy(info.name, driver);
2030 fstrcpy(info.defaultdatatype, "RAW");
2032 fstrcpy(info.driverpath, "");
2033 fstrcpy(info.datafile, "");
2034 fstrcpy(info.configfile, "");
2035 fstrcpy(info.helpfile, "");
2037 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2040 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2041 fstrcpy(info.dependentfiles[0], "");
2043 *info_ptr = memdup(&info, sizeof(info));
2048 /****************************************************************************
2049 ****************************************************************************/
2050 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2052 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2053 TDB_DATA kbuf, dbuf;
2054 const char *architecture;
2059 ZERO_STRUCT(driver);
2061 architecture = get_short_archi(arch);
2063 if ( !architecture )
2064 return WERR_UNKNOWN_PRINTER_DRIVER;
2066 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2068 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2071 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2073 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2076 kbuf.dsize = strlen(key)+1;
2078 dbuf = tdb_fetch(tdb_drivers, kbuf);
2080 return WERR_UNKNOWN_PRINTER_DRIVER;
2082 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2091 driver.defaultdatatype);
2094 while (len < dbuf.dsize) {
2095 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2096 if ( !driver.dependentfiles ) {
2097 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2101 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2102 &driver.dependentfiles[i]);
2106 if ( driver.dependentfiles )
2107 fstrcpy( driver.dependentfiles[i], "" );
2109 SAFE_FREE(dbuf.dptr);
2111 if (len != dbuf.dsize) {
2112 SAFE_FREE(driver.dependentfiles);
2114 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2117 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2122 /****************************************************************************
2123 Debugging function, dump at level 6 the struct in the logs.
2124 ****************************************************************************/
2126 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2129 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2132 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2138 if (driver.info_3 == NULL)
2141 info3=driver.info_3;
2143 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2144 DEBUGADD(20,("name:[%s]\n", info3->name));
2145 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2146 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2147 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2148 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2149 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2150 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2151 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2153 for (i=0; info3->dependentfiles &&
2154 *info3->dependentfiles[i]; i++) {
2155 DEBUGADD(20,("dependentfile:[%s]\n",
2156 info3->dependentfiles[i]));
2163 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2171 /****************************************************************************
2172 ****************************************************************************/
2173 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2177 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2182 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2183 nt_devmode->devicename,
2184 nt_devmode->formname,
2186 nt_devmode->specversion,
2187 nt_devmode->driverversion,
2189 nt_devmode->driverextra,
2190 nt_devmode->orientation,
2191 nt_devmode->papersize,
2192 nt_devmode->paperlength,
2193 nt_devmode->paperwidth,
2196 nt_devmode->defaultsource,
2197 nt_devmode->printquality,
2200 nt_devmode->yresolution,
2201 nt_devmode->ttoption,
2202 nt_devmode->collate,
2203 nt_devmode->logpixels,
2206 nt_devmode->bitsperpel,
2207 nt_devmode->pelswidth,
2208 nt_devmode->pelsheight,
2209 nt_devmode->displayflags,
2210 nt_devmode->displayfrequency,
2211 nt_devmode->icmmethod,
2212 nt_devmode->icmintent,
2213 nt_devmode->mediatype,
2214 nt_devmode->dithertype,
2215 nt_devmode->reserved1,
2216 nt_devmode->reserved2,
2217 nt_devmode->panningwidth,
2218 nt_devmode->panningheight,
2219 nt_devmode->nt_dev_private);
2222 if (nt_devmode->nt_dev_private) {
2223 len += tdb_pack(buf+len, buflen-len, "B",
2224 nt_devmode->driverextra,
2225 nt_devmode->nt_dev_private);
2228 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2233 /****************************************************************************
2234 Pack all values in all printer keys
2235 ***************************************************************************/
2237 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2241 REGISTRY_VALUE *val;
2242 REGVAL_CTR *val_ctr;
2249 /* loop over all keys */
2251 for ( i=0; i<data->num_keys; i++ ) {
2252 val_ctr = data->keys[i].values;
2253 num_values = regval_ctr_numvals( val_ctr );
2255 /* pack the keyname followed by a empty value */
2257 len += tdb_pack(buf+len, buflen-len, "pPdB",
2258 &data->keys[i].name,
2264 /* now loop over all values */
2266 for ( j=0; j<num_values; j++ ) {
2267 /* pathname should be stored as <key>\<value> */
2269 val = regval_ctr_specific_value( val_ctr, j );
2270 pstrcpy( path, data->keys[i].name );
2271 pstrcat( path, "\\" );
2272 pstrcat( path, regval_name(val) );
2274 len += tdb_pack(buf+len, buflen-len, "pPdB",
2279 regval_data_p(val) );
2281 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2288 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2294 /****************************************************************************
2295 Delete a printer - this just deletes the printer info file, any open
2296 handles are not affected.
2297 ****************************************************************************/
2299 uint32 del_a_printer(const char *sharename)
2303 pstring printdb_path;
2305 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2307 kbuf.dsize=strlen(key)+1;
2308 tdb_delete(tdb_printers, kbuf);
2310 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2312 kbuf.dsize=strlen(key)+1;
2313 tdb_delete(tdb_printers, kbuf);
2315 close_all_print_db();
2317 if (geteuid() == 0) {
2318 pstrcpy(printdb_path, lock_path("printing/"));
2319 pstrcat(printdb_path, sharename);
2320 pstrcat(printdb_path, ".tdb");
2322 unlink(printdb_path);
2328 /****************************************************************************
2329 ****************************************************************************/
2330 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2335 TDB_DATA kbuf, dbuf;
2338 * in addprinter: no servername and the printer is the name
2339 * in setprinter: servername is \\server
2340 * and printer is \\server\\printer
2342 * Samba manages only local printers.
2343 * we currently don't support things like i
2344 * path=\\other_server\printer
2346 * We only store the printername, not \\server\printername
2349 if ( info->servername[0] != '\0' ) {
2350 trim_string(info->printername, info->servername, NULL);
2351 trim_char(info->printername, '\\', '\0');
2352 info->servername[0]='\0';
2356 * JFM: one day I'll forget.
2357 * below that's info->portname because that's the SAMBA sharename
2358 * and I made NT 'thinks' it's the portname
2359 * the info->sharename is the thing you can name when you add a printer
2360 * that's the short-name when you create shared printer for 95/98
2361 * So I've made a limitation in SAMBA: you can only have 1 printer model
2362 * behind a SAMBA share.
2370 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2373 info->default_priority,
2390 info->printprocessor,
2394 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2396 len += pack_values( info->data, buf+len, buflen-len );
2398 if (buflen != len) {
2399 buf = (char *)SMB_REALLOC(buf, len);
2401 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2410 kbuf = make_printer_tdbkey( info->sharename );
2415 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2418 if (!W_ERROR_IS_OK(ret))
2419 DEBUG(8, ("error updating printer to tdb on disk\n"));
2423 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2424 info->sharename, info->drivername, info->portname, len));
2430 /****************************************************************************
2431 Malloc and return an NT devicemode.
2432 ****************************************************************************/
2434 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2437 char adevice[MAXDEVICENAME];
2438 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2440 if (nt_devmode == NULL) {
2441 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2445 ZERO_STRUCTP(nt_devmode);
2447 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2448 fstrcpy(nt_devmode->devicename, adevice);
2450 fstrcpy(nt_devmode->formname, "Letter");
2452 nt_devmode->specversion = 0x0401;
2453 nt_devmode->driverversion = 0x0400;
2454 nt_devmode->size = 0x00DC;
2455 nt_devmode->driverextra = 0x0000;
2456 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2457 DEFAULTSOURCE | COPIES | SCALE |
2458 PAPERSIZE | ORIENTATION;
2459 nt_devmode->orientation = 1;
2460 nt_devmode->papersize = PAPER_LETTER;
2461 nt_devmode->paperlength = 0;
2462 nt_devmode->paperwidth = 0;
2463 nt_devmode->scale = 0x64;
2464 nt_devmode->copies = 1;
2465 nt_devmode->defaultsource = BIN_FORMSOURCE;
2466 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2467 nt_devmode->color = COLOR_MONOCHROME;
2468 nt_devmode->duplex = DUP_SIMPLEX;
2469 nt_devmode->yresolution = 0;
2470 nt_devmode->ttoption = TT_SUBDEV;
2471 nt_devmode->collate = COLLATE_FALSE;
2472 nt_devmode->icmmethod = 0;
2473 nt_devmode->icmintent = 0;
2474 nt_devmode->mediatype = 0;
2475 nt_devmode->dithertype = 0;
2477 /* non utilisés par un driver d'imprimante */
2478 nt_devmode->logpixels = 0;
2479 nt_devmode->bitsperpel = 0;
2480 nt_devmode->pelswidth = 0;
2481 nt_devmode->pelsheight = 0;
2482 nt_devmode->displayflags = 0;
2483 nt_devmode->displayfrequency = 0;
2484 nt_devmode->reserved1 = 0;
2485 nt_devmode->reserved2 = 0;
2486 nt_devmode->panningwidth = 0;
2487 nt_devmode->panningheight = 0;
2489 nt_devmode->nt_dev_private = NULL;
2493 /****************************************************************************
2494 Deepcopy an NT devicemode.
2495 ****************************************************************************/
2497 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2499 NT_DEVICEMODE *new_nt_devicemode = NULL;
2501 if ( !nt_devicemode )
2504 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2505 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2509 new_nt_devicemode->nt_dev_private = NULL;
2510 if (nt_devicemode->nt_dev_private != NULL) {
2511 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2512 SAFE_FREE(new_nt_devicemode);
2513 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2518 return new_nt_devicemode;
2521 /****************************************************************************
2522 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2523 ****************************************************************************/
2525 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2527 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2529 if(nt_devmode == NULL)
2532 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2534 SAFE_FREE(nt_devmode->nt_dev_private);
2535 SAFE_FREE(*devmode_ptr);
2538 /****************************************************************************
2539 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2540 ****************************************************************************/
2542 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2544 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2549 free_nt_devicemode(&info->devmode);
2551 TALLOC_FREE( *info_ptr );
2555 /****************************************************************************
2556 ****************************************************************************/
2557 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2561 NT_DEVICEMODE devmode;
2563 ZERO_STRUCT(devmode);
2565 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2567 if (!*nt_devmode) return len;
2569 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2573 &devmode.specversion,
2574 &devmode.driverversion,
2576 &devmode.driverextra,
2577 &devmode.orientation,
2579 &devmode.paperlength,
2580 &devmode.paperwidth,
2583 &devmode.defaultsource,
2584 &devmode.printquality,
2587 &devmode.yresolution,
2593 &devmode.bitsperpel,
2595 &devmode.pelsheight,
2596 &devmode.displayflags,
2597 &devmode.displayfrequency,
2601 &devmode.dithertype,
2604 &devmode.panningwidth,
2605 &devmode.panningheight,
2606 &devmode.nt_dev_private);
2608 if (devmode.nt_dev_private) {
2609 /* the len in tdb_unpack is an int value and
2610 * devmode.driverextra is only a short
2612 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2613 devmode.driverextra=(uint16)extra_len;
2615 /* check to catch an invalid TDB entry so we don't segfault */
2616 if (devmode.driverextra == 0) {
2617 devmode.nt_dev_private = NULL;
2621 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2623 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2624 if (devmode.nt_dev_private)
2625 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2630 /****************************************************************************
2631 Allocate and initialize a new slot.
2632 ***************************************************************************/
2634 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2639 if ( !name || !data )
2642 /* allocate another slot in the NT_PRINTER_KEY array */
2644 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2645 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2651 key_index = data->num_keys;
2653 /* initialze new key */
2655 data->keys[key_index].name = talloc_strdup( data, name );
2657 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2662 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2667 /****************************************************************************
2668 search for a registry key name in the existing printer data
2669 ***************************************************************************/
2671 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2675 for ( i=0; i<data->num_keys; i++ ) {
2676 if ( strequal( data->keys[i].name, name ) ) {
2678 /* cleanup memory */
2680 TALLOC_FREE( data->keys[i].name );
2681 TALLOC_FREE( data->keys[i].values );
2683 /* if not the end of the array, move remaining elements down one slot */
2686 if ( data->num_keys && (i < data->num_keys) )
2687 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2694 return data->num_keys;
2697 /****************************************************************************
2698 search for a registry key name in the existing printer data
2699 ***************************************************************************/
2701 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2706 if ( !data || !name )
2709 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2711 /* loop over all existing keys */
2713 for ( i=0; i<data->num_keys; i++ ) {
2714 if ( strequal(data->keys[i].name, name) ) {
2715 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2725 /****************************************************************************
2726 ***************************************************************************/
2728 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2732 int num_subkeys = 0;
2734 fstring *subkeys_ptr = NULL;
2743 /* special case of asking for the top level printer data registry key names */
2745 if ( strlen(key) == 0 ) {
2746 for ( i=0; i<data->num_keys; i++ ) {
2748 /* found a match, so allocate space and copy the name */
2750 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2751 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2756 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2763 /* asking for the subkeys of some key */
2764 /* subkey paths are stored in the key name using '\' as the delimiter */
2766 for ( i=0; i<data->num_keys; i++ ) {
2767 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2769 /* if we found the exact key, then break */
2770 key_len = strlen( key );
2771 if ( strlen(data->keys[i].name) == key_len )
2774 /* get subkey path */
2776 p = data->keys[i].name + key_len;
2779 fstrcpy( subkeyname, p );
2780 if ( (p = strchr( subkeyname, '\\' )) )
2783 /* don't add a key more than once */
2785 for ( j=0; j<num_subkeys; j++ ) {
2786 if ( strequal( subkeys_ptr[j], subkeyname ) )
2790 if ( j != num_subkeys )
2793 /* found a match, so allocate space and copy the name */
2795 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2796 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2801 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2807 /* return error if the key was not found */
2809 if ( i == data->num_keys ) {
2810 SAFE_FREE(subkeys_ptr);
2815 /* tag off the end */
2818 fstrcpy(subkeys_ptr[num_subkeys], "" );
2820 *subkeys = subkeys_ptr;
2826 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2829 smb_ucs2_t conv_str[1024];
2832 regval_ctr_delvalue(ctr, val_name);
2833 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2834 STR_TERMINATE | STR_NOALIGN);
2835 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2836 (char *) conv_str, str_size);
2839 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2842 regval_ctr_delvalue(ctr, val_name);
2843 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2844 (char *) &dword, sizeof(dword));
2847 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2850 uint8 bin_bool = (b ? 1 : 0);
2851 regval_ctr_delvalue(ctr, val_name);
2852 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2853 (char *) &bin_bool, sizeof(bin_bool));
2856 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2857 const char *multi_sz)
2859 smb_ucs2_t *conv_strs = NULL;
2862 /* a multi-sz has to have a null string terminator, i.e., the last
2863 string must be followed by two nulls */
2864 str_size = strlen(multi_sz) + 2;
2865 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2870 /* Change to byte units. */
2871 str_size *= sizeof(smb_ucs2_t);
2872 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2873 STR_TERMINATE | STR_NOALIGN);
2875 regval_ctr_delvalue(ctr, val_name);
2876 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2877 (char *) conv_strs, str_size);
2878 safe_free(conv_strs);
2882 /****************************************************************************
2883 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2885 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2886 * @return BOOL indicating success or failure
2887 ***************************************************************************/
2889 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2891 REGVAL_CTR *ctr = NULL;
2894 char *allocated_string = NULL;
2895 const char *ascii_str;
2898 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2899 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2900 ctr = info2->data->keys[i].values;
2902 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2903 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2905 /* we make the assumption that the netbios name is the same
2906 as the DNS name sinc ethe former will be what we used to
2909 if ( get_mydnsdomname( dnssuffix ) )
2910 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2912 fstrcpy( longname, global_myname() );
2914 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2916 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2917 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2918 SAFE_FREE(allocated_string);
2920 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2921 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2922 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2923 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2924 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2925 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2926 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2927 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2928 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2930 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2931 (info2->attributes &
2932 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2934 switch (info2->attributes & 0x3) {
2936 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2939 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2942 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2945 ascii_str = "unknown";
2947 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2952 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2956 REGVAL_CTR *ctr=NULL;
2958 /* find the DsSpooler key */
2959 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2960 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2961 ctr = info2->data->keys[i].values;
2963 regval_ctr_delvalue(ctr, "objectGUID");
2964 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2965 (char *) &guid, sizeof(struct uuid));
2968 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2969 NT_PRINTER_INFO_LEVEL *printer)
2973 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2974 char *srv_dn_utf8, **srv_cn_utf8;
2977 const char *attrs[] = {"objectGUID", NULL};
2979 WERROR win_rc = WERR_OK;
2981 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2983 /* figure out where to publish */
2984 ads_find_machine_acct(ads, &res, global_myname());
2986 /* We use ldap_get_dn here as we need the answer
2987 * in utf8 to call ldap_explode_dn(). JRA. */
2989 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2992 return WERR_SERVER_UNAVAILABLE;
2994 ads_msgfree(ads, res);
2995 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2997 ldap_memfree(srv_dn_utf8);
2999 return WERR_SERVER_UNAVAILABLE;
3001 /* Now convert to CH_UNIX. */
3002 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3003 ldap_memfree(srv_dn_utf8);
3004 ldap_memfree(srv_cn_utf8);
3006 return WERR_SERVER_UNAVAILABLE;
3008 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3009 ldap_memfree(srv_dn_utf8);
3010 ldap_memfree(srv_cn_utf8);
3013 return WERR_SERVER_UNAVAILABLE;
3016 ldap_memfree(srv_dn_utf8);
3017 ldap_memfree(srv_cn_utf8);
3019 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
3020 printer->info_2->sharename, srv_dn);
3023 SAFE_FREE(srv_cn_0);
3025 /* build the ads mods */
3026 ctx = talloc_init("nt_printer_publish_ads");
3027 mods = ads_init_mods(ctx);
3029 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3030 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3031 printer->info_2->sharename);
3034 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3035 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3036 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3038 if (!ADS_ERR_OK(ads_rc))
3039 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3041 talloc_destroy(ctx);
3043 /* retreive the guid and store it locally */
3044 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3046 ads_pull_guid(ads, res, &guid);
3047 ads_msgfree(ads, res);
3048 store_printer_guid(printer->info_2, guid);
3049 win_rc = mod_a_printer(printer, 2);
3056 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3057 NT_PRINTER_INFO_LEVEL *printer)
3061 char *prt_dn = NULL;
3063 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3065 /* remove the printer from the directory */
3066 ads_rc = ads_find_printer_on_server(ads, &res,
3067 printer->info_2->sharename, global_myname());
3069 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3070 prt_dn = ads_get_dn(ads, res);
3071 ads_rc = ads_del_dn(ads, prt_dn);
3072 ads_memfree(ads, prt_dn);
3075 ads_msgfree(ads, res);
3079 /****************************************************************************
3080 * Publish a printer in the directory
3082 * @param snum describing printer service
3083 * @return WERROR indicating status of publishing
3084 ***************************************************************************/
3086 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3089 ADS_STRUCT *ads = NULL;
3090 NT_PRINTER_INFO_LEVEL *printer = NULL;
3093 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3094 if (!W_ERROR_IS_OK(win_rc))
3098 case SPOOL_DS_PUBLISH:
3099 case SPOOL_DS_UPDATE:
3100 /* set the DsSpooler info and attributes */
3101 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3102 win_rc = WERR_NOMEM;
3106 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3108 case SPOOL_DS_UNPUBLISH:
3109 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3112 win_rc = WERR_NOT_SUPPORTED;
3116 win_rc = mod_a_printer(printer, 2);
3117 if (!W_ERROR_IS_OK(win_rc)) {
3118 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3122 ads = ads_init(NULL, NULL, NULL);
3124 DEBUG(3, ("ads_init() failed\n"));
3125 win_rc = WERR_SERVER_UNAVAILABLE;
3128 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3129 SAFE_FREE(ads->auth.password);
3130 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3133 /* ads_connect() will find the DC for us */
3134 ads_rc = ads_connect(ads);
3135 if (!ADS_ERR_OK(ads_rc)) {
3136 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3137 win_rc = WERR_ACCESS_DENIED;
3142 case SPOOL_DS_PUBLISH:
3143 case SPOOL_DS_UPDATE:
3144 win_rc = nt_printer_publish_ads(ads, printer);
3146 case SPOOL_DS_UNPUBLISH:
3147 win_rc = nt_printer_unpublish_ads(ads, printer);
3152 free_a_printer(&printer, 2);
3157 WERROR check_published_printers(void)
3160 ADS_STRUCT *ads = NULL;
3162 int n_services = lp_numservices();
3163 NT_PRINTER_INFO_LEVEL *printer = NULL;
3165 ads = ads_init(NULL, NULL, NULL);
3167 DEBUG(3, ("ads_init() failed\n"));
3168 return WERR_SERVER_UNAVAILABLE;
3170 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3171 SAFE_FREE(ads->auth.password);
3172 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3175 /* ads_connect() will find the DC for us */
3176 ads_rc = ads_connect(ads);
3177 if (!ADS_ERR_OK(ads_rc)) {
3178 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3180 return WERR_ACCESS_DENIED;
3183 for (snum = 0; snum < n_services; snum++) {
3184 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3187 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3188 lp_servicename(snum))) &&
3189 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3190 nt_printer_publish_ads(ads, printer);
3192 free_a_printer(&printer, 2);
3199 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3202 NT_PRINTER_INFO_LEVEL *printer = NULL;
3204 REGISTRY_VALUE *guid_val;
3208 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3210 if (!W_ERROR_IS_OK(win_rc) ||
3211 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3212 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3213 !(ctr = printer->info_2->data->keys[i].values) ||
3214 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3216 free_a_printer(&printer, 2);
3220 /* fetching printer guids really ought to be a separate function.. */
3221 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3222 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3224 free_a_printer(&printer, 2);
3228 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3233 WERROR check_published_printers(void)
3238 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3243 #endif /* HAVE_ADS */
3245 /****************************************************************************
3246 ***************************************************************************/
3248 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3250 NT_PRINTER_DATA *data;
3252 int removed_keys = 0;
3256 empty_slot = data->num_keys;
3259 return WERR_INVALID_PARAM;
3261 /* remove all keys */
3263 if ( !strlen(key) ) {
3265 TALLOC_FREE( data );
3269 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3275 /* remove a specific key (and all subkeys) */
3277 for ( i=0; i<data->num_keys; i++ ) {
3278 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3279 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3280 data->keys[i].name));
3282 TALLOC_FREE( data->keys[i].name );
3283 TALLOC_FREE( data->keys[i].values );
3285 /* mark the slot as empty */
3287 ZERO_STRUCTP( &data->keys[i] );
3291 /* find the first empty slot */
3293 for ( i=0; i<data->num_keys; i++ ) {
3294 if ( !data->keys[i].name ) {
3301 if ( i == data->num_keys )
3302 /* nothing was removed */
3303 return WERR_INVALID_PARAM;
3305 /* move everything down */
3307 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3308 if ( data->keys[i].name ) {
3309 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3310 ZERO_STRUCTP( &data->keys[i] );
3318 data->num_keys -= removed_keys;
3320 /* sanity check to see if anything is left */
3322 if ( !data->num_keys ) {
3323 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3325 SAFE_FREE( data->keys );
3326 ZERO_STRUCTP( data );
3332 /****************************************************************************
3333 ***************************************************************************/
3335 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3337 WERROR result = WERR_OK;
3340 /* we must have names on non-zero length */
3342 if ( !key || !*key|| !value || !*value )
3343 return WERR_INVALID_NAME;
3345 /* find the printer key first */
3347 key_index = lookup_printerkey( p2->data, key );
3348 if ( key_index == -1 )
3351 /* make sure the value exists so we can return the correct error code */
3353 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3354 return WERR_BADFILE;
3356 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3358 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3364 /****************************************************************************
3365 ***************************************************************************/
3367 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3368 uint32 type, uint8 *data, int real_len )
3370 WERROR result = WERR_OK;
3373 /* we must have names on non-zero length */
3375 if ( !key || !*key|| !value || !*value )
3376 return WERR_INVALID_NAME;
3378 /* find the printer key first */
3380 key_index = lookup_printerkey( p2->data, key );
3381 if ( key_index == -1 )
3382 key_index = add_new_printer_key( p2->data, key );
3384 if ( key_index == -1 )
3387 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3388 type, (const char *)data, real_len );
3390 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3391 key, value, type, real_len ));
3396 /****************************************************************************
3397 ***************************************************************************/
3399 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3403 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3406 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3409 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3412 /****************************************************************************
3413 Unpack a list of registry values frem the TDB
3414 ***************************************************************************/
3416 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3420 pstring string, valuename, keyname;
3424 REGISTRY_VALUE *regval_p;
3427 /* add the "PrinterDriverData" key first for performance reasons */
3429 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3431 /* loop and unpack the rest of the registry values */
3435 /* check to see if there are any more registry values */
3438 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3442 /* unpack the next regval */
3444 len += tdb_unpack(buf+len, buflen-len, "fdB",
3450 /* lookup for subkey names which have a type of REG_NONE */
3451 /* there's no data with this entry */
3453 if ( type == REG_NONE ) {
3454 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3455 add_new_printer_key( printer_data, string );
3460 * break of the keyname from the value name.
3461 * Valuenames can have embedded '\'s so be careful.
3462 * only support one level of keys. See the
3463 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3467 str = strchr_m( string, '\\');
3469 /* Put in "PrinterDriverData" is no key specified */
3472 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3473 pstrcpy( valuename, string );
3477 pstrcpy( keyname, string );
3478 pstrcpy( valuename, str+1 );
3481 /* see if we need a new key */
3483 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3484 key_index = add_new_printer_key( printer_data, keyname );
3486 if ( key_index == -1 ) {
3487 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3492 /* add the new value */
3494 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3496 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3498 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3504 /****************************************************************************
3505 ***************************************************************************/
3507 static void map_to_os2_driver(fstring drivername)
3509 static BOOL initialised=False;
3510 static fstring last_from,last_to;
3511 char *mapfile = lp_os2_driver_map();
3512 char **lines = NULL;
3516 if (!strlen(drivername))
3523 *last_from = *last_to = 0;
3527 if (strequal(drivername,last_from)) {
3528 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3529 fstrcpy(drivername,last_to);
3533 lines = file_lines_load(mapfile, &numlines,0);
3534 if (numlines == 0 || lines == NULL) {
3535 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3540 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3542 for( i = 0; i < numlines; i++) {
3543 char *nt_name = lines[i];
3544 char *os2_name = strchr(nt_name,'=');
3551 while (isspace(*nt_name))
3554 if (!*nt_name || strchr("#;",*nt_name))
3558 int l = strlen(nt_name);
3559 while (l && isspace(nt_name[l-1])) {
3565 while (isspace(*os2_name))
3569 int l = strlen(os2_name);
3570 while (l && isspace(os2_name[l-1])) {
3576 if (strequal(nt_name,drivername)) {
3577 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3578 fstrcpy(last_from,drivername);
3579 fstrcpy(last_to,os2_name);
3580 fstrcpy(drivername,os2_name);
3581 file_lines_free(lines);
3586 file_lines_free(lines);
3589 /****************************************************************************
3590 Get a default printer info 2 struct.
3591 ****************************************************************************/
3592 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3596 snum = lp_servicenumber(sharename);
3598 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3599 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3600 servername, sharename);
3601 fstrcpy(info->sharename, sharename);
3602 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3604 /* by setting the driver name to an empty string, a local NT admin
3605 can now run the **local** APW to install a local printer driver
3606 for a Samba shared printer in 2.2. Without this, drivers **must** be
3607 installed on the Samba server for NT clients --jerry */
3608 #if 0 /* JERRY --do not uncomment-- */
3609 if (!*info->drivername)
3610 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3614 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3616 pstrcpy(info->comment, "");
3617 fstrcpy(info->printprocessor, "winprint");
3618 fstrcpy(info->datatype, "RAW");
3620 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3622 info->starttime = 0; /* Minutes since 12:00am GMT */
3623 info->untiltime = 0; /* Minutes since 12:00am GMT */
3625 info->default_priority = 1;
3626 info->setuptime = (uint32)time(NULL);
3629 * I changed this as I think it is better to have a generic
3630 * DEVMODE than to crash Win2k explorer.exe --jerry
3631 * See the HP Deskjet 990c Win2k drivers for an example.
3633 * However the default devmode appears to cause problems
3634 * with the HP CLJ 8500 PCL driver. Hence the addition of
3635 * the "default devmode" parameter --jerry 22/01/2002
3638 if (lp_default_devmode(snum)) {
3639 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3643 info->devmode = NULL;
3646 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3653 free_nt_devicemode(&info->devmode);
3655 return WERR_ACCESS_DENIED;
3658 /****************************************************************************
3659 ****************************************************************************/
3660 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3663 int snum = lp_servicenumber(sharename);
3664 TDB_DATA kbuf, dbuf;
3665 fstring printername;
3666 char adevice[MAXDEVICENAME];
3668 kbuf = make_printer_tdbkey( sharename );
3670 dbuf = tdb_fetch(tdb_printers, kbuf);
3672 return get_a_printer_2_default(info, servername, sharename);
3674 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3677 &info->default_priority,
3684 &info->c_setprinter,
3694 info->printprocessor,
3698 /* Samba has to have shared raw drivers. */
3699 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3700 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3702 /* Restore the stripped strings. */
3703 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3705 if ( lp_force_printername(snum) )
3706 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3708 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3710 fstrcpy(info->printername, printername);
3712 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3715 * Some client drivers freak out if there is a NULL devmode
3716 * (probably the driver is not checking before accessing
3717 * the devmode pointer) --jerry
3719 * See comments in get_a_printer_2_default()
3722 if (lp_default_devmode(snum) && !info->devmode) {
3723 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3725 info->devmode = construct_nt_devicemode(printername);
3728 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3729 if (info->devmode) {
3730 fstrcpy(info->devmode->devicename, adevice);
3733 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3734 DEBUG(0,("unpack_values: talloc() failed!\n"));
3737 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3739 /* This will get the current RPC talloc context, but we should be
3740 passing this as a parameter... fixme... JRA ! */
3742 nt_printing_getsec(info, sharename, &info->secdesc_buf);
3744 /* Fix for OS/2 drivers. */
3746 if (get_remote_arch() == RA_OS2)
3747 map_to_os2_driver(info->drivername);
3749 SAFE_FREE(dbuf.dptr);
3751 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3752 sharename, info->printername, info->drivername));
3757 /****************************************************************************
3758 Debugging function, dump at level 6 the struct in the logs.
3759 ****************************************************************************/
3760 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3763 NT_PRINTER_INFO_LEVEL_2 *info2;
3765 DEBUG(106,("Dumping printer at level [%d]\n", level));
3770 if (printer->info_2 == NULL)
3774 info2=printer->info_2;
3776 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3777 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3778 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3779 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3780 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3781 DEBUGADD(106,("status:[%d]\n", info2->status));
3782 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3783 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3784 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3785 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3786 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3788 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3789 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3790 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3791 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3792 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3793 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3794 DEBUGADD(106,("location:[%s]\n", info2->location));
3795 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3796 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3797 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3798 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3804 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3812 /****************************************************************************
3813 Update the changeid time.
3814 This is SO NASTY as some drivers need this to change, others need it
3815 static. This value will change every second, and I must hope that this
3816 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3818 ****************************************************************************/
3820 static uint32 rev_changeid(void)
3824 get_process_uptime(&tv);
3827 /* Return changeid as msec since spooler restart */
3828 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3831 * This setting seems to work well but is too untested
3832 * to replace the above calculation. Left in for experiementation
3833 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3835 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3841 * The function below are the high level ones.
3842 * only those ones must be called from the spoolss code.
3846 /****************************************************************************
3847 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3848 ****************************************************************************/
3850 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3854 dump_a_printer(printer, level);
3860 * Update the changestamp. Emperical tests show that the
3861 * ChangeID is always updated,but c_setprinter is
3862 * global spooler variable (not per printer).
3865 /* ChangeID **must** be increasing over the lifetime
3866 of client's spoolss service in order for the
3867 client's cache to show updates */
3869 printer->info_2->changeid = rev_changeid();
3872 * Because one day someone will ask:
3873 * NT->NT An admin connection to a remote
3874 * printer show changes imeediately in
3875 * the properities dialog
3877 * A non-admin connection will only show the
3878 * changes after viewing the properites page
3879 * 2 times. Seems to be related to a
3880 * race condition in the client between the spooler
3881 * updating the local cache and the Explorer.exe GUI
3882 * actually displaying the properties.
3884 * This is fixed in Win2k. admin/non-admin
3885 * connections both display changes immediately.
3890 result=update_a_printer_2(printer->info_2);
3895 result=WERR_UNKNOWN_LEVEL;
3902 /****************************************************************************
3903 Initialize printer devmode & data with previously saved driver init values.
3904 ****************************************************************************/
3906 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3910 TDB_DATA kbuf, dbuf;
3911 NT_PRINTER_INFO_LEVEL_2 info;
3917 * Delete any printer data 'values' already set. When called for driver
3918 * replace, there will generally be some, but during an add printer, there
3919 * should not be any (if there are delete them).
3922 if ( info_ptr->data )
3923 delete_all_printer_data( info_ptr, "" );
3925 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3928 kbuf.dsize = strlen(key)+1;
3930 dbuf = tdb_fetch(tdb_drivers, kbuf);
3933 * When changing to a driver that has no init info in the tdb, remove
3934 * the previous drivers init info and leave the new on blank.
3936 free_nt_devicemode(&info_ptr->devmode);
3941 * Get the saved DEVMODE..
3944 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3947 * The saved DEVMODE contains the devicename from the printer used during
3948 * the initialization save. Change it to reflect the new printer.
3951 if ( info.devmode ) {
3952 ZERO_STRUCT(info.devmode->devicename);
3953 fstrcpy(info.devmode->devicename, info_ptr->printername);
3957 * NT/2k does not change out the entire DeviceMode of a printer
3958 * when changing the driver. Only the driverextra, private, &
3959 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3961 * Later examination revealed that Windows NT/2k does reset the
3962 * the printer's device mode, bit **only** when you change a
3963 * property of the device mode such as the page orientation.
3968 /* Bind the saved DEVMODE to the new the printer */
3970 free_nt_devicemode(&info_ptr->devmode);
3971 info_ptr->devmode = info.devmode;
3973 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3974 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3976 /* Add the printer data 'values' to the new printer */
3978 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3979 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3983 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3986 SAFE_FREE(dbuf.dptr);
3991 /****************************************************************************
3992 Initialize printer devmode & data with previously saved driver init values.
3993 When a printer is created using AddPrinter, the drivername bound to the
3994 printer is used to lookup previously saved driver initialization info, which
3995 is bound to the new printer.
3996 ****************************************************************************/
3998 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4000 BOOL result = False;
4004 result = set_driver_init_2(printer->info_2);
4008 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4016 /****************************************************************************
4017 Delete driver init data stored for a specified driver
4018 ****************************************************************************/
4020 BOOL del_driver_init(char *drivername)
4025 if (!drivername || !*drivername) {
4026 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4030 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4033 kbuf.dsize = strlen(key)+1;
4035 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4037 return (tdb_delete(tdb_drivers, kbuf) == 0);
4040 /****************************************************************************
4041 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4042 in the tdb. Note: this is different from the driver entry and the printer
4043 entry. There should be a single driver init entry for each driver regardless
4044 of whether it was installed from NT or 2K. Technically, they should be
4045 different, but they work out to the same struct.
4046 ****************************************************************************/
4048 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4052 int buflen, len, ret;
4053 TDB_DATA kbuf, dbuf;
4060 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4062 len += pack_values( info->data, buf+len, buflen-len );
4065 buf = (char *)SMB_REALLOC(buf, len);
4067 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4075 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4078 kbuf.dsize = strlen(key)+1;
4082 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4086 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4090 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4091 info->sharename, info->drivername));
4096 /****************************************************************************
4097 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4098 ****************************************************************************/
4100 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4104 dump_a_printer(printer, level);
4108 result = update_driver_init_2(printer->info_2);
4118 /****************************************************************************
4119 Convert the printer data value, a REG_BINARY array, into an initialization
4120 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4121 got to keep the endians happy :).
4122 ****************************************************************************/
4124 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4126 BOOL result = False;
4130 ZERO_STRUCT(devmode);
4132 prs_init(&ps, 0, ctx, UNMARSHALL);
4133 ps.data_p = (char *)data;
4134 ps.buffer_size = data_len;
4136 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4137 result = convert_devicemode("", &devmode, &nt_devmode);
4139 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4144 /****************************************************************************
4145 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4147 1. Use the driver's config DLL to this UNC printername and:
4148 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4149 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4150 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4152 The last step triggers saving the "driver initialization" information for
4153 this printer into the tdb. Later, new printers that use this driver will
4154 have this initialization information bound to them. This simulates the
4155 driver initialization, as if it had run on the Samba server (as it would
4158 The Win32 client side code requirement sucks! But until we can run arbitrary
4159 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4161 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4162 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4163 about it and you will realize why. JRR 010720
4164 ****************************************************************************/
4166 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4168 WERROR status = WERR_OK;
4169 TALLOC_CTX *ctx = NULL;
4170 NT_DEVICEMODE *nt_devmode = NULL;
4171 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4174 * When the DEVMODE is already set on the printer, don't try to unpack it.
4176 DEBUG(8,("save_driver_init_2: Enter...\n"));
4178 if ( !printer->info_2->devmode && data_len ) {
4180 * Set devmode on printer info, so entire printer initialization can be
4184 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4187 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4188 status = WERR_NOMEM;
4192 ZERO_STRUCTP(nt_devmode);
4195 * The DEVMODE is held in the 'data' component of the param in raw binary.
4196 * Convert it to to a devmode structure
4198 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4199 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4200 status = WERR_INVALID_PARAM;
4204 printer->info_2->devmode = nt_devmode;
4208 * Pack up and add (or update) the DEVMODE and any current printer data to
4209 * a 'driver init' element in the tdb
4213 if ( update_driver_init(printer, 2) != 0 ) {
4214 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4215 status = WERR_NOMEM;
4220 * If driver initialization info was successfully saved, set the current
4221 * printer to match it. This allows initialization of the current printer
4222 * as well as the driver.
4224 status = mod_a_printer(printer, 2);
4225 if (!W_ERROR_IS_OK(status)) {
4226 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4227 printer->info_2->printername));
4231 talloc_destroy(ctx);
4232 free_nt_devicemode( &nt_devmode );
4234 printer->info_2->devmode = tmp_devmode;
4239 /****************************************************************************
4240 Update the driver init info (DEVMODE and specifics) for a printer
4241 ****************************************************************************/
4243 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4245 WERROR status = WERR_OK;
4249 status = save_driver_init_2( printer, data, data_len );
4252 status = WERR_UNKNOWN_LEVEL;
4259 /****************************************************************************
4260 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4262 Previously the code had a memory allocation problem because it always
4263 used the TALLOC_CTX from the Printer_entry*. This context lasts
4264 as a long as the original handle is open. So if the client made a lot
4265 of getprinter[data]() calls, the memory usage would climb. Now we use
4266 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4267 still use the Printer_entry->ctx for maintaining the cache copy though
4268 since that object must live as long as the handle by definition.
4271 ****************************************************************************/
4273 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4274 const char *sharename)
4279 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4281 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4282 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4288 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4289 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4290 TALLOC_FREE( *pp_printer );
4295 fstrcpy( servername, print_hnd->servername );
4297 fstrcpy( servername, "%L" );
4298 standard_sub_basic( "", servername, sizeof(servername)-1 );
4301 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4304 /* we have a new printer now. Save it with this handle */
4306 if ( !W_ERROR_IS_OK(result) ) {
4307 TALLOC_FREE( *pp_printer );
4308 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4309 sharename, (unsigned int)level, dos_errstr(result)));
4313 dump_a_printer( *pp_printer, level);
4318 TALLOC_FREE( *pp_printer );
4319 return WERR_UNKNOWN_LEVEL;
4325 /****************************************************************************
4326 Deletes a NT_PRINTER_INFO_LEVEL struct.
4327 ****************************************************************************/
4329 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4331 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4338 if ( printer->info_2 )
4339 free_nt_printer_info_level_2(&printer->info_2);
4343 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4347 TALLOC_FREE(*pp_printer);
4352 /****************************************************************************
4353 ****************************************************************************/
4354 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4357 DEBUG(104,("adding a printer at level [%d]\n", level));
4358 dump_a_printer_driver(driver, level);
4362 result=add_a_printer_driver_3(driver.info_3);
4366 result=add_a_printer_driver_6(driver.info_6);
4376 /****************************************************************************
4377 ****************************************************************************/
4379 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4380 fstring drivername, const char *architecture, uint32 version)
4386 /* Sometime we just want any version of the driver */
4388 if ( version == DRIVER_ANY_VERSION ) {
4389 /* look for Win2k first and then for NT4 */
4390 result = get_a_printer_driver_3(&driver->info_3, drivername,
4393 if ( !W_ERROR_IS_OK(result) ) {
4394 result = get_a_printer_driver_3( &driver->info_3,
4395 drivername, architecture, 2 );
4398 result = get_a_printer_driver_3(&driver->info_3, drivername,
4399 architecture, version);
4408 if (W_ERROR_IS_OK(result))
4409 dump_a_printer_driver(*driver, level);
4414 /****************************************************************************
4415 ****************************************************************************/
4416 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4423 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4424 if (driver.info_3 != NULL)
4426 info3=driver.info_3;
4427 SAFE_FREE(info3->dependentfiles);
4428 ZERO_STRUCTP(info3);
4438 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4439 if (driver.info_6 != NULL) {
4440 info6=driver.info_6;
4441 SAFE_FREE(info6->dependentfiles);
4442 SAFE_FREE(info6->previousnames);
4443 ZERO_STRUCTP(info6);
4459 /****************************************************************************
4460 Determine whether or not a particular driver is currently assigned
4462 ****************************************************************************/
4464 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4467 int n_services = lp_numservices();
4468 NT_PRINTER_INFO_LEVEL *printer = NULL;
4469 BOOL in_use = False;
4474 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4476 /* loop through the printers.tdb and check for the drivername */
4478 for (snum=0; snum<n_services && !in_use; snum++) {
4479 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4482 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4485 if ( strequal(info_3->name, printer->info_2->drivername) )
4488 free_a_printer( &printer, 2 );
4491 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4494 NT_PRINTER_DRIVER_INFO_LEVEL d;
4497 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4499 /* we can still remove the driver if there is one of
4500 "Windows NT x86" version 2 or 3 left */
4502 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4503 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4506 switch ( info_3->cversion ) {
4508 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4511 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4514 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4516 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4521 /* now check the error code */
4523 if ( W_ERROR_IS_OK(werr) ) {
4524 /* it's ok to remove the driver, we have other architctures left */
4526 free_a_printer_driver( d, 3 );
4530 /* report that the driver is not in use by default */
4536 /**********************************************************************
4537 Check to see if a ogiven file is in use by *info
4538 *********************************************************************/
4540 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4547 if ( strequal(file, info->driverpath) )
4550 if ( strequal(file, info->datafile) )
4553 if ( strequal(file, info->configfile) )
4556 if ( strequal(file, info->helpfile) )
4559 /* see of there are any dependent files to examine */
4561 if ( !info->dependentfiles )
4564 while ( *info->dependentfiles[i] ) {
4565 if ( strequal(file, info->dependentfiles[i]) )
4574 /**********************************************************************
4575 Utility function to remove the dependent file pointed to by the
4576 input parameter from the list
4577 *********************************************************************/
4579 static void trim_dependent_file( fstring files[], int idx )
4582 /* bump everything down a slot */
4584 while( *files[idx+1] ) {
4585 fstrcpy( files[idx], files[idx+1] );
4594 /**********************************************************************
4595 Check if any of the files used by src are also used by drv
4596 *********************************************************************/
4598 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4599 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4601 BOOL in_use = False;
4607 /* check each file. Remove it from the src structure if it overlaps */
4609 if ( drv_file_in_use(src->driverpath, drv) ) {
4611 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4612 fstrcpy( src->driverpath, "" );
4615 if ( drv_file_in_use(src->datafile, drv) ) {
4617 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4618 fstrcpy( src->datafile, "" );
4621 if ( drv_file_in_use(src->configfile, drv) ) {
4623 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4624 fstrcpy( src->configfile, "" );
4627 if ( drv_file_in_use(src->helpfile, drv) ) {
4629 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4630 fstrcpy( src->helpfile, "" );
4633 /* are there any dependentfiles to examine? */
4635 if ( !src->dependentfiles )
4638 while ( *src->dependentfiles[i] ) {
4639 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4641 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4642 trim_dependent_file( src->dependentfiles, i );
4650 /****************************************************************************
4651 Determine whether or not a particular driver files are currently being
4652 used by any other driver.
4654 Return value is True if any files were in use by other drivers
4655 and False otherwise.
4657 Upon return, *info has been modified to only contain the driver files
4658 which are not in use
4659 ****************************************************************************/
4661 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4666 fstring *list = NULL;
4667 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4672 version = info->cversion;
4674 /* loop over all driver versions */
4676 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4678 /* get the list of drivers */
4681 ndrivers = get_ntdrivers(&list, info->environment, version);
4683 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4684 ndrivers, info->environment, version));
4686 /* check each driver for overlap in files */
4688 for (i=0; i<ndrivers; i++) {
4689 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4691 ZERO_STRUCT(driver);
4693 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4698 /* check if d2 uses any files from d1 */
4699 /* only if this is a different driver than the one being deleted */
4701 if ( !strequal(info->name, driver.info_3->name) ) {
4702 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4703 free_a_printer_driver(driver, 3);
4709 free_a_printer_driver(driver, 3);
4714 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4716 driver.info_3 = info;
4718 if ( DEBUGLEVEL >= 20 )
4719 dump_a_printer_driver( driver, 3 );
4724 /****************************************************************************
4725 Actually delete the driver files. Make sure that
4726 printer_driver_files_in_use() return False before calling
4728 ****************************************************************************/
4730 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4735 connection_struct *conn;
4745 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4748 * Connect to the print$ share under the same account as the
4749 * user connected to the rpc pipe. Note we must be root to
4753 null_pw = data_blob( NULL, 0 );
4754 fstrcpy(res_type, "A:");
4756 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4760 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4764 if ( !CAN_WRITE(conn) ) {
4765 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4769 /* Save who we are - we are temporarily becoming the connection user. */
4771 if ( !become_user(conn, conn->vuid) ) {
4772 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4776 /* now delete the files; must strip the '\print$' string from
4779 if ( *info_3->driverpath ) {
4780 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4782 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4783 DEBUG(10,("deleting driverfile [%s]\n", s));
4784 unlink_internals(conn, 0, file, False);
4788 if ( *info_3->configfile ) {
4789 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4791 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4792 DEBUG(10,("deleting configfile [%s]\n", s));
4793 unlink_internals(conn, 0, file, False);
4797 if ( *info_3->datafile ) {
4798 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4800 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4801 DEBUG(10,("deleting datafile [%s]\n", s));
4802 unlink_internals(conn, 0, file, False);
4806 if ( *info_3->helpfile ) {
4807 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4809 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4810 DEBUG(10,("deleting helpfile [%s]\n", s));
4811 unlink_internals(conn, 0, file, False);
4815 /* check if we are done removing files */
4817 if ( info_3->dependentfiles ) {
4818 while ( info_3->dependentfiles[i][0] ) {
4821 /* bypass the "\print$" portion of the path */
4823 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4825 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4826 DEBUG(10,("deleting dependent file [%s]\n", file));
4827 unlink_internals(conn, 0, file, False);
4839 /****************************************************************************
4840 Remove a printer driver from the TDB. This assumes that the the driver was
4841 previously looked up.
4842 ***************************************************************************/
4844 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4845 uint32 version, BOOL delete_files )
4849 TDB_DATA kbuf, dbuf;
4850 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4852 /* delete the tdb data first */
4854 arch = get_short_archi(info_3->environment);
4855 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4856 arch, version, info_3->name);
4858 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4859 key, delete_files ? "TRUE" : "FALSE" ));
4861 ctr.info_3 = info_3;
4862 dump_a_printer_driver( ctr, 3 );
4865 kbuf.dsize=strlen(key)+1;
4867 /* check if the driver actually exists for this environment */
4869 dbuf = tdb_fetch( tdb_drivers, kbuf );
4871 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4872 return WERR_UNKNOWN_PRINTER_DRIVER;
4875 SAFE_FREE( dbuf.dptr );
4877 /* ok... the driver exists so the delete should return success */
4879 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4880 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4881 return WERR_ACCESS_DENIED;
4885 * now delete any associated files if delete_files == True
4886 * even if this part failes, we return succes because the
4887 * driver doesn not exist any more
4891 delete_driver_files( info_3, user );
4894 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4899 /****************************************************************************
4900 Store a security desc for a printer.
4901 ****************************************************************************/
4903 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4905 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4906 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4908 TALLOC_CTX *mem_ctx = NULL;
4912 mem_ctx = talloc_init("nt_printing_setsec");
4913 if (mem_ctx == NULL)
4916 /* The old owner and group sids of the security descriptor are not
4917 present when new ACEs are added or removed by changing printer
4918 permissions through NT. If they are NULL in the new security
4919 descriptor then copy them over from the old one. */
4921 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4922 DOM_SID *owner_sid, *group_sid;
4923 SEC_ACL *dacl, *sacl;
4924 SEC_DESC *psd = NULL;
4927 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4929 /* Pick out correct owner and group sids */
4931 owner_sid = secdesc_ctr->sec->owner_sid ?
4932 secdesc_ctr->sec->owner_sid :
4933 old_secdesc_ctr->sec->owner_sid;
4935 group_sid = secdesc_ctr->sec->grp_sid ?
4936 secdesc_ctr->sec->grp_sid :
4937 old_secdesc_ctr->sec->grp_sid;
4939 dacl = secdesc_ctr->sec->dacl ?
4940 secdesc_ctr->sec->dacl :
4941 old_secdesc_ctr->sec->dacl;
4943 sacl = secdesc_ctr->sec->sacl ?
4944 secdesc_ctr->sec->sacl :
4945 old_secdesc_ctr->sec->sacl;
4947 /* Make a deep copy of the security descriptor */
4949 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4950 owner_sid, group_sid,
4955 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4958 if (!new_secdesc_ctr) {
4959 new_secdesc_ctr = secdesc_ctr;
4962 /* Store the security descriptor in a tdb */
4964 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4965 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4967 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4969 status = WERR_BADFUNC;
4973 key = make_printers_secdesc_tdbkey( sharename );
4975 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4978 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4979 status = WERR_BADFUNC;
4982 /* Free malloc'ed memory */
4988 talloc_destroy(mem_ctx);
4992 /****************************************************************************
4993 Construct a default security descriptor buffer for a printer.
4994 ****************************************************************************/
4996 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4998 SEC_ACE ace[5]; /* max number of ace entries */
5001 SEC_ACL *psa = NULL;
5002 SEC_DESC_BUF *sdb = NULL;
5003 SEC_DESC *psd = NULL;
5007 /* Create an ACE where Everyone is allowed to print */
5009 init_sec_access(&sa, PRINTER_ACE_PRINT);
5010 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5011 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5013 /* Add the domain admins group if we are a DC */
5016 DOM_SID domadmins_sid;
5018 sid_copy(&domadmins_sid, get_global_sam_sid());
5019 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5021 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5022 init_sec_ace(&ace[i++], &domadmins_sid,
5023 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5024 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5025 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5026 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5028 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5029 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5031 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5032 init_sec_ace(&ace[i++], &adm_sid,
5033 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5034 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5035 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5036 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5039 /* add BUILTIN\Administrators as FULL CONTROL */
5041 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5042 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5043 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5044 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5045 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5046 SEC_ACE_TYPE_ACCESS_ALLOWED,
5047 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5049 /* Make the security descriptor owned by the BUILTIN\Administrators */
5051 /* The ACL revision number in rpc_secdesc.h differs from the one
5052 created by NT when setting ACE entries in printer
5053 descriptors. NT4 complains about the property being edited by a
5056 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5057 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5058 &global_sid_Builtin_Administrators,
5059 &global_sid_Builtin_Administrators,
5060 NULL, psa, &sd_size);
5064 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5068 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5070 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5071 (unsigned int)sd_size));
5076 /****************************************************************************
5077 Get a security desc for a printer.
5078 ****************************************************************************/
5080 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5086 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5087 sharename = temp + 1;
5090 /* Fetch security descriptor from tdb */
5092 key = make_printers_secdesc_tdbkey( sharename );
5094 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5095 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5097 DEBUG(4,("using default secdesc for %s\n", sharename));
5099 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5103 /* Save default security descriptor for later */
5105 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5106 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5108 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5109 tdb_prs_store(tdb_printers, key, &ps);
5116 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5117 this security descriptor has been created when winbindd was
5118 down. Take ownership of security descriptor. */
5120 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5123 /* Change sd owner to workgroup administrator */
5125 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5126 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5127 SEC_DESC *psd = NULL;
5132 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5134 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5136 (*secdesc_ctr)->sec->grp_sid,
5137 (*secdesc_ctr)->sec->sacl,
5138 (*secdesc_ctr)->sec->dacl,
5141 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5143 /* Swap with other one */
5145 *secdesc_ctr = new_secdesc_ctr;
5149 nt_printing_setsec(sharename, *secdesc_ctr);
5153 if (DEBUGLEVEL >= 10) {
5154 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5157 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5158 sharename, the_acl->num_aces));
5160 for (i = 0; i < the_acl->num_aces; i++) {
5163 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5165 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5166 the_acl->ace[i].type, the_acl->ace[i].flags,
5167 the_acl->ace[i].info.mask));
5177 1: level not implemented
5178 2: file doesn't exist
5179 3: can't allocate memory
5180 4: can't free memory
5181 5: non existant struct
5185 A printer and a printer driver are 2 different things.
5186 NT manages them separatelly, Samba does the same.
5187 Why ? Simply because it's easier and it makes sense !
5189 Now explanation: You have 3 printers behind your samba server,
5190 2 of them are the same make and model (laser A and B). But laser B
5191 has an 3000 sheet feeder and laser A doesn't such an option.
5192 Your third printer is an old dot-matrix model for the accounting :-).
5194 If the /usr/local/samba/lib directory (default dir), you will have
5195 5 files to describe all of this.
5197 3 files for the printers (1 by printer):
5200 NTprinter_accounting
5201 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5202 NTdriver_printer model X
5203 NTdriver_printer model Y
5205 jfm: I should use this comment for the text file to explain
5206 same thing for the forms BTW.
5207 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5211 /* Convert generic access rights to printer object specific access rights.
5212 It turns out that NT4 security descriptors use generic access rights and
5213 NT5 the object specific ones. */
5215 void map_printer_permissions(SEC_DESC *sd)
5219 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5220 se_map_generic(&sd->dacl->ace[i].info.mask,
5221 &printer_generic_mapping);
5225 /****************************************************************************
5226 Check a user has permissions to perform the given operation. We use the
5227 permission constants defined in include/rpc_spoolss.h to check the various
5228 actions we perform when checking printer access.
5230 PRINTER_ACCESS_ADMINISTER:
5231 print_queue_pause, print_queue_resume, update_printer_sec,
5232 update_printer, spoolss_addprinterex_level_2,
5233 _spoolss_setprinterdata
5238 JOB_ACCESS_ADMINISTER:
5239 print_job_delete, print_job_pause, print_job_resume,
5242 Try access control in the following order (for performance reasons):
5243 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5244 2) check security descriptor (bit comparisons in memory)
5245 3) "printer admins" (may result in numerous calls to winbind)
5247 ****************************************************************************/
5248 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5250 SEC_DESC_BUF *secdesc = NULL;
5251 uint32 access_granted;
5255 TALLOC_CTX *mem_ctx = NULL;
5256 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5258 /* If user is NULL then use the current_user structure */
5261 user = ¤t_user;
5263 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5265 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5269 /* Get printer name */
5271 pname = PRINTERNAME(snum);
5273 if (!pname || !*pname) {
5278 /* Get printer security descriptor */
5280 if(!(mem_ctx = talloc_init("print_access_check"))) {
5285 nt_printing_getsec(mem_ctx, pname, &secdesc);
5287 if (access_type == JOB_ACCESS_ADMINISTER) {
5288 SEC_DESC_BUF *parent_secdesc = secdesc;
5290 /* Create a child security descriptor to check permissions
5291 against. This is because print jobs are child objects
5292 objects of a printer. */
5294 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5296 /* Now this is the bit that really confuses me. The access
5297 type needs to be changed from JOB_ACCESS_ADMINISTER to
5298 PRINTER_ACCESS_ADMINISTER for this to work. Something
5299 to do with the child (job) object becoming like a
5302 access_type = PRINTER_ACCESS_ADMINISTER;
5307 map_printer_permissions(secdesc->sec);
5309 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5310 &access_granted, &status);
5312 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5314 /* see if we need to try the printer admin list */
5316 if ((access_granted == 0) &&
5317 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5318 user->nt_user_token,
5319 lp_printer_admin(snum)))) {
5323 talloc_destroy(mem_ctx);
5331 /****************************************************************************
5332 Check the time parameters allow a print operation.
5333 *****************************************************************************/
5335 BOOL print_time_access_check(int snum)
5337 NT_PRINTER_INFO_LEVEL *printer = NULL;
5339 time_t now = time(NULL);
5343 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5346 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5350 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5352 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5355 free_a_printer(&printer, 2);
5363 /****************************************************************************
5364 Fill in the servername sent in the _spoolss_open_printer_ex() call
5365 ****************************************************************************/
5367 char* get_server_name( Printer_entry *printer )
5369 return printer->servername;