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)
2302 pstring printdb_path;
2304 kbuf = make_printer_tdbkey( sharename );
2305 tdb_delete(tdb_printers, kbuf);
2307 kbuf.dptr = make_printers_secdesc_tdbkey( sharename );
2308 kbuf.dsize = strlen(kbuf.dptr) + 1;
2309 tdb_delete(tdb_printers, kbuf);
2311 close_all_print_db();
2313 if (geteuid() == 0) {
2314 pstrcpy(printdb_path, lock_path("printing/"));
2315 pstrcat(printdb_path, sharename);
2316 pstrcat(printdb_path, ".tdb");
2318 unlink(printdb_path);
2324 /****************************************************************************
2325 ****************************************************************************/
2326 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2331 TDB_DATA kbuf, dbuf;
2334 * in addprinter: no servername and the printer is the name
2335 * in setprinter: servername is \\server
2336 * and printer is \\server\\printer
2338 * Samba manages only local printers.
2339 * we currently don't support things like i
2340 * path=\\other_server\printer
2342 * We only store the printername, not \\server\printername
2345 if ( info->servername[0] != '\0' ) {
2346 trim_string(info->printername, info->servername, NULL);
2347 trim_char(info->printername, '\\', '\0');
2348 info->servername[0]='\0';
2352 * JFM: one day I'll forget.
2353 * below that's info->portname because that's the SAMBA sharename
2354 * and I made NT 'thinks' it's the portname
2355 * the info->sharename is the thing you can name when you add a printer
2356 * that's the short-name when you create shared printer for 95/98
2357 * So I've made a limitation in SAMBA: you can only have 1 printer model
2358 * behind a SAMBA share.
2366 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2369 info->default_priority,
2386 info->printprocessor,
2390 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2392 len += pack_values( info->data, buf+len, buflen-len );
2394 if (buflen != len) {
2395 buf = (char *)SMB_REALLOC(buf, len);
2397 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2406 kbuf = make_printer_tdbkey( info->sharename );
2411 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2414 if (!W_ERROR_IS_OK(ret))
2415 DEBUG(8, ("error updating printer to tdb on disk\n"));
2419 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2420 info->sharename, info->drivername, info->portname, len));
2426 /****************************************************************************
2427 Malloc and return an NT devicemode.
2428 ****************************************************************************/
2430 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2433 char adevice[MAXDEVICENAME];
2434 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2436 if (nt_devmode == NULL) {
2437 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2441 ZERO_STRUCTP(nt_devmode);
2443 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2444 fstrcpy(nt_devmode->devicename, adevice);
2446 fstrcpy(nt_devmode->formname, "Letter");
2448 nt_devmode->specversion = 0x0401;
2449 nt_devmode->driverversion = 0x0400;
2450 nt_devmode->size = 0x00DC;
2451 nt_devmode->driverextra = 0x0000;
2452 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2453 DEFAULTSOURCE | COPIES | SCALE |
2454 PAPERSIZE | ORIENTATION;
2455 nt_devmode->orientation = 1;
2456 nt_devmode->papersize = PAPER_LETTER;
2457 nt_devmode->paperlength = 0;
2458 nt_devmode->paperwidth = 0;
2459 nt_devmode->scale = 0x64;
2460 nt_devmode->copies = 1;
2461 nt_devmode->defaultsource = BIN_FORMSOURCE;
2462 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2463 nt_devmode->color = COLOR_MONOCHROME;
2464 nt_devmode->duplex = DUP_SIMPLEX;
2465 nt_devmode->yresolution = 0;
2466 nt_devmode->ttoption = TT_SUBDEV;
2467 nt_devmode->collate = COLLATE_FALSE;
2468 nt_devmode->icmmethod = 0;
2469 nt_devmode->icmintent = 0;
2470 nt_devmode->mediatype = 0;
2471 nt_devmode->dithertype = 0;
2473 /* non utilisés par un driver d'imprimante */
2474 nt_devmode->logpixels = 0;
2475 nt_devmode->bitsperpel = 0;
2476 nt_devmode->pelswidth = 0;
2477 nt_devmode->pelsheight = 0;
2478 nt_devmode->displayflags = 0;
2479 nt_devmode->displayfrequency = 0;
2480 nt_devmode->reserved1 = 0;
2481 nt_devmode->reserved2 = 0;
2482 nt_devmode->panningwidth = 0;
2483 nt_devmode->panningheight = 0;
2485 nt_devmode->nt_dev_private = NULL;
2489 /****************************************************************************
2490 Deepcopy an NT devicemode.
2491 ****************************************************************************/
2493 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2495 NT_DEVICEMODE *new_nt_devicemode = NULL;
2497 if ( !nt_devicemode )
2500 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2501 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2505 new_nt_devicemode->nt_dev_private = NULL;
2506 if (nt_devicemode->nt_dev_private != NULL) {
2507 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2508 SAFE_FREE(new_nt_devicemode);
2509 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2514 return new_nt_devicemode;
2517 /****************************************************************************
2518 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2519 ****************************************************************************/
2521 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2523 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2525 if(nt_devmode == NULL)
2528 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2530 SAFE_FREE(nt_devmode->nt_dev_private);
2531 SAFE_FREE(*devmode_ptr);
2534 /****************************************************************************
2535 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2536 ****************************************************************************/
2538 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2540 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2545 free_nt_devicemode(&info->devmode);
2547 TALLOC_FREE( *info_ptr );
2551 /****************************************************************************
2552 ****************************************************************************/
2553 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2557 NT_DEVICEMODE devmode;
2559 ZERO_STRUCT(devmode);
2561 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2563 if (!*nt_devmode) return len;
2565 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2569 &devmode.specversion,
2570 &devmode.driverversion,
2572 &devmode.driverextra,
2573 &devmode.orientation,
2575 &devmode.paperlength,
2576 &devmode.paperwidth,
2579 &devmode.defaultsource,
2580 &devmode.printquality,
2583 &devmode.yresolution,
2589 &devmode.bitsperpel,
2591 &devmode.pelsheight,
2592 &devmode.displayflags,
2593 &devmode.displayfrequency,
2597 &devmode.dithertype,
2600 &devmode.panningwidth,
2601 &devmode.panningheight,
2602 &devmode.nt_dev_private);
2604 if (devmode.nt_dev_private) {
2605 /* the len in tdb_unpack is an int value and
2606 * devmode.driverextra is only a short
2608 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2609 devmode.driverextra=(uint16)extra_len;
2611 /* check to catch an invalid TDB entry so we don't segfault */
2612 if (devmode.driverextra == 0) {
2613 devmode.nt_dev_private = NULL;
2617 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2619 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2620 if (devmode.nt_dev_private)
2621 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2626 /****************************************************************************
2627 Allocate and initialize a new slot.
2628 ***************************************************************************/
2630 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2635 if ( !name || !data )
2638 /* allocate another slot in the NT_PRINTER_KEY array */
2640 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2641 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2647 key_index = data->num_keys;
2649 /* initialze new key */
2651 data->keys[key_index].name = talloc_strdup( data, name );
2653 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2658 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2663 /****************************************************************************
2664 search for a registry key name in the existing printer data
2665 ***************************************************************************/
2667 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2671 for ( i=0; i<data->num_keys; i++ ) {
2672 if ( strequal( data->keys[i].name, name ) ) {
2674 /* cleanup memory */
2676 TALLOC_FREE( data->keys[i].name );
2677 TALLOC_FREE( data->keys[i].values );
2679 /* if not the end of the array, move remaining elements down one slot */
2682 if ( data->num_keys && (i < data->num_keys) )
2683 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2690 return data->num_keys;
2693 /****************************************************************************
2694 search for a registry key name in the existing printer data
2695 ***************************************************************************/
2697 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2702 if ( !data || !name )
2705 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2707 /* loop over all existing keys */
2709 for ( i=0; i<data->num_keys; i++ ) {
2710 if ( strequal(data->keys[i].name, name) ) {
2711 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2721 /****************************************************************************
2722 ***************************************************************************/
2724 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2728 int num_subkeys = 0;
2730 fstring *subkeys_ptr = NULL;
2739 /* special case of asking for the top level printer data registry key names */
2741 if ( strlen(key) == 0 ) {
2742 for ( i=0; i<data->num_keys; i++ ) {
2744 /* found a match, so allocate space and copy the name */
2746 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2747 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2752 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2759 /* asking for the subkeys of some key */
2760 /* subkey paths are stored in the key name using '\' as the delimiter */
2762 for ( i=0; i<data->num_keys; i++ ) {
2763 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2765 /* if we found the exact key, then break */
2766 key_len = strlen( key );
2767 if ( strlen(data->keys[i].name) == key_len )
2770 /* get subkey path */
2772 p = data->keys[i].name + key_len;
2775 fstrcpy( subkeyname, p );
2776 if ( (p = strchr( subkeyname, '\\' )) )
2779 /* don't add a key more than once */
2781 for ( j=0; j<num_subkeys; j++ ) {
2782 if ( strequal( subkeys_ptr[j], subkeyname ) )
2786 if ( j != num_subkeys )
2789 /* found a match, so allocate space and copy the name */
2791 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2792 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2797 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2803 /* return error if the key was not found */
2805 if ( i == data->num_keys ) {
2806 SAFE_FREE(subkeys_ptr);
2811 /* tag off the end */
2814 fstrcpy(subkeys_ptr[num_subkeys], "" );
2816 *subkeys = subkeys_ptr;
2822 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2825 smb_ucs2_t conv_str[1024];
2828 regval_ctr_delvalue(ctr, val_name);
2829 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2830 STR_TERMINATE | STR_NOALIGN);
2831 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2832 (char *) conv_str, str_size);
2835 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2838 regval_ctr_delvalue(ctr, val_name);
2839 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2840 (char *) &dword, sizeof(dword));
2843 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2846 uint8 bin_bool = (b ? 1 : 0);
2847 regval_ctr_delvalue(ctr, val_name);
2848 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2849 (char *) &bin_bool, sizeof(bin_bool));
2852 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2853 const char *multi_sz)
2855 smb_ucs2_t *conv_strs = NULL;
2858 /* a multi-sz has to have a null string terminator, i.e., the last
2859 string must be followed by two nulls */
2860 str_size = strlen(multi_sz) + 2;
2861 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2866 /* Change to byte units. */
2867 str_size *= sizeof(smb_ucs2_t);
2868 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2869 STR_TERMINATE | STR_NOALIGN);
2871 regval_ctr_delvalue(ctr, val_name);
2872 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2873 (char *) conv_strs, str_size);
2874 safe_free(conv_strs);
2878 /****************************************************************************
2879 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2881 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2882 * @return BOOL indicating success or failure
2883 ***************************************************************************/
2885 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2887 REGVAL_CTR *ctr = NULL;
2890 char *allocated_string = NULL;
2891 const char *ascii_str;
2894 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2895 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2896 ctr = info2->data->keys[i].values;
2898 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2899 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2901 /* we make the assumption that the netbios name is the same
2902 as the DNS name sinc ethe former will be what we used to
2905 if ( get_mydnsdomname( dnssuffix ) )
2906 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2908 fstrcpy( longname, global_myname() );
2910 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2912 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2913 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2914 SAFE_FREE(allocated_string);
2916 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2917 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2918 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2919 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2920 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2921 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2922 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2923 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2924 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2926 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2927 (info2->attributes &
2928 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2930 switch (info2->attributes & 0x3) {
2932 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2935 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2938 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2941 ascii_str = "unknown";
2943 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2948 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2952 REGVAL_CTR *ctr=NULL;
2954 /* find the DsSpooler key */
2955 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2956 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2957 ctr = info2->data->keys[i].values;
2959 regval_ctr_delvalue(ctr, "objectGUID");
2960 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2961 (char *) &guid, sizeof(struct uuid));
2964 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2965 NT_PRINTER_INFO_LEVEL *printer)
2969 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2970 char *srv_dn_utf8, **srv_cn_utf8;
2973 const char *attrs[] = {"objectGUID", NULL};
2975 WERROR win_rc = WERR_OK;
2977 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2979 /* figure out where to publish */
2980 ads_find_machine_acct(ads, &res, global_myname());
2982 /* We use ldap_get_dn here as we need the answer
2983 * in utf8 to call ldap_explode_dn(). JRA. */
2985 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2988 return WERR_SERVER_UNAVAILABLE;
2990 ads_msgfree(ads, res);
2991 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2993 ldap_memfree(srv_dn_utf8);
2995 return WERR_SERVER_UNAVAILABLE;
2997 /* Now convert to CH_UNIX. */
2998 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2999 ldap_memfree(srv_dn_utf8);
3000 ldap_memfree(srv_cn_utf8);
3002 return WERR_SERVER_UNAVAILABLE;
3004 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3005 ldap_memfree(srv_dn_utf8);
3006 ldap_memfree(srv_cn_utf8);
3009 return WERR_SERVER_UNAVAILABLE;
3012 ldap_memfree(srv_dn_utf8);
3013 ldap_memfree(srv_cn_utf8);
3015 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
3016 printer->info_2->sharename, srv_dn);
3019 SAFE_FREE(srv_cn_0);
3021 /* build the ads mods */
3022 ctx = talloc_init("nt_printer_publish_ads");
3023 mods = ads_init_mods(ctx);
3025 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3026 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3027 printer->info_2->sharename);
3030 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3031 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3032 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3034 if (!ADS_ERR_OK(ads_rc))
3035 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3037 talloc_destroy(ctx);
3039 /* retreive the guid and store it locally */
3040 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3042 ads_pull_guid(ads, res, &guid);
3043 ads_msgfree(ads, res);
3044 store_printer_guid(printer->info_2, guid);
3045 win_rc = mod_a_printer(printer, 2);
3052 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3053 NT_PRINTER_INFO_LEVEL *printer)
3057 char *prt_dn = NULL;
3059 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3061 /* remove the printer from the directory */
3062 ads_rc = ads_find_printer_on_server(ads, &res,
3063 printer->info_2->sharename, global_myname());
3065 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3066 prt_dn = ads_get_dn(ads, res);
3067 ads_rc = ads_del_dn(ads, prt_dn);
3068 ads_memfree(ads, prt_dn);
3071 ads_msgfree(ads, res);
3075 /****************************************************************************
3076 * Publish a printer in the directory
3078 * @param snum describing printer service
3079 * @return WERROR indicating status of publishing
3080 ***************************************************************************/
3082 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3085 ADS_STRUCT *ads = NULL;
3086 NT_PRINTER_INFO_LEVEL *printer = NULL;
3089 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3090 if (!W_ERROR_IS_OK(win_rc))
3094 case SPOOL_DS_PUBLISH:
3095 case SPOOL_DS_UPDATE:
3096 /* set the DsSpooler info and attributes */
3097 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3098 win_rc = WERR_NOMEM;
3102 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3104 case SPOOL_DS_UNPUBLISH:
3105 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3108 win_rc = WERR_NOT_SUPPORTED;
3112 win_rc = mod_a_printer(printer, 2);
3113 if (!W_ERROR_IS_OK(win_rc)) {
3114 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3118 ads = ads_init(NULL, NULL, NULL);
3120 DEBUG(3, ("ads_init() failed\n"));
3121 win_rc = WERR_SERVER_UNAVAILABLE;
3124 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3125 SAFE_FREE(ads->auth.password);
3126 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3129 /* ads_connect() will find the DC for us */
3130 ads_rc = ads_connect(ads);
3131 if (!ADS_ERR_OK(ads_rc)) {
3132 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3133 win_rc = WERR_ACCESS_DENIED;
3138 case SPOOL_DS_PUBLISH:
3139 case SPOOL_DS_UPDATE:
3140 win_rc = nt_printer_publish_ads(ads, printer);
3142 case SPOOL_DS_UNPUBLISH:
3143 win_rc = nt_printer_unpublish_ads(ads, printer);
3148 free_a_printer(&printer, 2);
3153 WERROR check_published_printers(void)
3156 ADS_STRUCT *ads = NULL;
3158 int n_services = lp_numservices();
3159 NT_PRINTER_INFO_LEVEL *printer = NULL;
3161 ads = ads_init(NULL, NULL, NULL);
3163 DEBUG(3, ("ads_init() failed\n"));
3164 return WERR_SERVER_UNAVAILABLE;
3166 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3167 SAFE_FREE(ads->auth.password);
3168 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3171 /* ads_connect() will find the DC for us */
3172 ads_rc = ads_connect(ads);
3173 if (!ADS_ERR_OK(ads_rc)) {
3174 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3176 return WERR_ACCESS_DENIED;
3179 for (snum = 0; snum < n_services; snum++) {
3180 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3183 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3184 lp_servicename(snum))) &&
3185 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3186 nt_printer_publish_ads(ads, printer);
3188 free_a_printer(&printer, 2);
3195 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3198 NT_PRINTER_INFO_LEVEL *printer = NULL;
3200 REGISTRY_VALUE *guid_val;
3204 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3206 if (!W_ERROR_IS_OK(win_rc) ||
3207 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3208 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3209 !(ctr = printer->info_2->data->keys[i].values) ||
3210 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3212 free_a_printer(&printer, 2);
3216 /* fetching printer guids really ought to be a separate function.. */
3217 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3218 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3220 free_a_printer(&printer, 2);
3224 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3229 WERROR check_published_printers(void)
3234 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3239 #endif /* HAVE_ADS */
3241 /****************************************************************************
3242 ***************************************************************************/
3244 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3246 NT_PRINTER_DATA *data;
3248 int removed_keys = 0;
3252 empty_slot = data->num_keys;
3255 return WERR_INVALID_PARAM;
3257 /* remove all keys */
3259 if ( !strlen(key) ) {
3261 TALLOC_FREE( data );
3265 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3271 /* remove a specific key (and all subkeys) */
3273 for ( i=0; i<data->num_keys; i++ ) {
3274 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3275 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3276 data->keys[i].name));
3278 TALLOC_FREE( data->keys[i].name );
3279 TALLOC_FREE( data->keys[i].values );
3281 /* mark the slot as empty */
3283 ZERO_STRUCTP( &data->keys[i] );
3287 /* find the first empty slot */
3289 for ( i=0; i<data->num_keys; i++ ) {
3290 if ( !data->keys[i].name ) {
3297 if ( i == data->num_keys )
3298 /* nothing was removed */
3299 return WERR_INVALID_PARAM;
3301 /* move everything down */
3303 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3304 if ( data->keys[i].name ) {
3305 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3306 ZERO_STRUCTP( &data->keys[i] );
3314 data->num_keys -= removed_keys;
3316 /* sanity check to see if anything is left */
3318 if ( !data->num_keys ) {
3319 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3321 SAFE_FREE( data->keys );
3322 ZERO_STRUCTP( data );
3328 /****************************************************************************
3329 ***************************************************************************/
3331 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3333 WERROR result = WERR_OK;
3336 /* we must have names on non-zero length */
3338 if ( !key || !*key|| !value || !*value )
3339 return WERR_INVALID_NAME;
3341 /* find the printer key first */
3343 key_index = lookup_printerkey( p2->data, key );
3344 if ( key_index == -1 )
3347 /* make sure the value exists so we can return the correct error code */
3349 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3350 return WERR_BADFILE;
3352 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3354 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3360 /****************************************************************************
3361 ***************************************************************************/
3363 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3364 uint32 type, uint8 *data, int real_len )
3366 WERROR result = WERR_OK;
3369 /* we must have names on non-zero length */
3371 if ( !key || !*key|| !value || !*value )
3372 return WERR_INVALID_NAME;
3374 /* find the printer key first */
3376 key_index = lookup_printerkey( p2->data, key );
3377 if ( key_index == -1 )
3378 key_index = add_new_printer_key( p2->data, key );
3380 if ( key_index == -1 )
3383 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3384 type, (const char *)data, real_len );
3386 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3387 key, value, type, real_len ));
3392 /****************************************************************************
3393 ***************************************************************************/
3395 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3399 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3402 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3405 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3408 /****************************************************************************
3409 Unpack a list of registry values frem the TDB
3410 ***************************************************************************/
3412 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3416 pstring string, valuename, keyname;
3420 REGISTRY_VALUE *regval_p;
3423 /* add the "PrinterDriverData" key first for performance reasons */
3425 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3427 /* loop and unpack the rest of the registry values */
3431 /* check to see if there are any more registry values */
3434 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3438 /* unpack the next regval */
3440 len += tdb_unpack(buf+len, buflen-len, "fdB",
3446 /* lookup for subkey names which have a type of REG_NONE */
3447 /* there's no data with this entry */
3449 if ( type == REG_NONE ) {
3450 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3451 add_new_printer_key( printer_data, string );
3456 * break of the keyname from the value name.
3457 * Valuenames can have embedded '\'s so be careful.
3458 * only support one level of keys. See the
3459 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3463 str = strchr_m( string, '\\');
3465 /* Put in "PrinterDriverData" is no key specified */
3468 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3469 pstrcpy( valuename, string );
3473 pstrcpy( keyname, string );
3474 pstrcpy( valuename, str+1 );
3477 /* see if we need a new key */
3479 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3480 key_index = add_new_printer_key( printer_data, keyname );
3482 if ( key_index == -1 ) {
3483 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3488 /* add the new value */
3490 regval_ctr_addvalue( printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3492 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3494 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3500 /****************************************************************************
3501 ***************************************************************************/
3503 static void map_to_os2_driver(fstring drivername)
3505 static BOOL initialised=False;
3506 static fstring last_from,last_to;
3507 char *mapfile = lp_os2_driver_map();
3508 char **lines = NULL;
3512 if (!strlen(drivername))
3519 *last_from = *last_to = 0;
3523 if (strequal(drivername,last_from)) {
3524 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3525 fstrcpy(drivername,last_to);
3529 lines = file_lines_load(mapfile, &numlines,0);
3530 if (numlines == 0 || lines == NULL) {
3531 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3536 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3538 for( i = 0; i < numlines; i++) {
3539 char *nt_name = lines[i];
3540 char *os2_name = strchr(nt_name,'=');
3547 while (isspace(*nt_name))
3550 if (!*nt_name || strchr("#;",*nt_name))
3554 int l = strlen(nt_name);
3555 while (l && isspace(nt_name[l-1])) {
3561 while (isspace(*os2_name))
3565 int l = strlen(os2_name);
3566 while (l && isspace(os2_name[l-1])) {
3572 if (strequal(nt_name,drivername)) {
3573 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3574 fstrcpy(last_from,drivername);
3575 fstrcpy(last_to,os2_name);
3576 fstrcpy(drivername,os2_name);
3577 file_lines_free(lines);
3582 file_lines_free(lines);
3585 /****************************************************************************
3586 Get a default printer info 2 struct.
3587 ****************************************************************************/
3588 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3592 snum = lp_servicenumber(sharename);
3594 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3595 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3596 servername, sharename);
3597 fstrcpy(info->sharename, sharename);
3598 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3600 /* by setting the driver name to an empty string, a local NT admin
3601 can now run the **local** APW to install a local printer driver
3602 for a Samba shared printer in 2.2. Without this, drivers **must** be
3603 installed on the Samba server for NT clients --jerry */
3604 #if 0 /* JERRY --do not uncomment-- */
3605 if (!*info->drivername)
3606 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3610 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3612 pstrcpy(info->comment, "");
3613 fstrcpy(info->printprocessor, "winprint");
3614 fstrcpy(info->datatype, "RAW");
3616 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3618 info->starttime = 0; /* Minutes since 12:00am GMT */
3619 info->untiltime = 0; /* Minutes since 12:00am GMT */
3621 info->default_priority = 1;
3622 info->setuptime = (uint32)time(NULL);
3625 * I changed this as I think it is better to have a generic
3626 * DEVMODE than to crash Win2k explorer.exe --jerry
3627 * See the HP Deskjet 990c Win2k drivers for an example.
3629 * However the default devmode appears to cause problems
3630 * with the HP CLJ 8500 PCL driver. Hence the addition of
3631 * the "default devmode" parameter --jerry 22/01/2002
3634 if (lp_default_devmode(snum)) {
3635 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL)
3639 info->devmode = NULL;
3642 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf))
3649 free_nt_devicemode(&info->devmode);
3651 return WERR_ACCESS_DENIED;
3654 /****************************************************************************
3655 ****************************************************************************/
3656 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3659 int snum = lp_servicenumber(sharename);
3660 TDB_DATA kbuf, dbuf;
3661 fstring printername;
3662 char adevice[MAXDEVICENAME];
3664 kbuf = make_printer_tdbkey( sharename );
3666 dbuf = tdb_fetch(tdb_printers, kbuf);
3668 return get_a_printer_2_default(info, servername, sharename);
3670 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3673 &info->default_priority,
3680 &info->c_setprinter,
3690 info->printprocessor,
3694 /* Samba has to have shared raw drivers. */
3695 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3696 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3698 /* Restore the stripped strings. */
3699 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3701 if ( lp_force_printername(snum) )
3702 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3704 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3706 fstrcpy(info->printername, printername);
3708 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3711 * Some client drivers freak out if there is a NULL devmode
3712 * (probably the driver is not checking before accessing
3713 * the devmode pointer) --jerry
3715 * See comments in get_a_printer_2_default()
3718 if (lp_default_devmode(snum) && !info->devmode) {
3719 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3721 info->devmode = construct_nt_devicemode(printername);
3724 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3725 if (info->devmode) {
3726 fstrcpy(info->devmode->devicename, adevice);
3729 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3730 DEBUG(0,("unpack_values: talloc() failed!\n"));
3733 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3735 /* This will get the current RPC talloc context, but we should be
3736 passing this as a parameter... fixme... JRA ! */
3738 nt_printing_getsec(info, sharename, &info->secdesc_buf);
3740 /* Fix for OS/2 drivers. */
3742 if (get_remote_arch() == RA_OS2)
3743 map_to_os2_driver(info->drivername);
3745 SAFE_FREE(dbuf.dptr);
3747 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3748 sharename, info->printername, info->drivername));
3753 /****************************************************************************
3754 Debugging function, dump at level 6 the struct in the logs.
3755 ****************************************************************************/
3756 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3759 NT_PRINTER_INFO_LEVEL_2 *info2;
3761 DEBUG(106,("Dumping printer at level [%d]\n", level));
3766 if (printer->info_2 == NULL)
3770 info2=printer->info_2;
3772 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3773 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3774 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3775 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3776 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3777 DEBUGADD(106,("status:[%d]\n", info2->status));
3778 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3779 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3780 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3781 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3782 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3784 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3785 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3786 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3787 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3788 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3789 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3790 DEBUGADD(106,("location:[%s]\n", info2->location));
3791 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3792 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3793 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3794 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3800 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3808 /****************************************************************************
3809 Update the changeid time.
3810 This is SO NASTY as some drivers need this to change, others need it
3811 static. This value will change every second, and I must hope that this
3812 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3814 ****************************************************************************/
3816 static uint32 rev_changeid(void)
3820 get_process_uptime(&tv);
3823 /* Return changeid as msec since spooler restart */
3824 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3827 * This setting seems to work well but is too untested
3828 * to replace the above calculation. Left in for experiementation
3829 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3831 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3837 * The function below are the high level ones.
3838 * only those ones must be called from the spoolss code.
3842 /****************************************************************************
3843 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3844 ****************************************************************************/
3846 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3850 dump_a_printer(printer, level);
3856 * Update the changestamp. Emperical tests show that the
3857 * ChangeID is always updated,but c_setprinter is
3858 * global spooler variable (not per printer).
3861 /* ChangeID **must** be increasing over the lifetime
3862 of client's spoolss service in order for the
3863 client's cache to show updates */
3865 printer->info_2->changeid = rev_changeid();
3868 * Because one day someone will ask:
3869 * NT->NT An admin connection to a remote
3870 * printer show changes imeediately in
3871 * the properities dialog
3873 * A non-admin connection will only show the
3874 * changes after viewing the properites page
3875 * 2 times. Seems to be related to a
3876 * race condition in the client between the spooler
3877 * updating the local cache and the Explorer.exe GUI
3878 * actually displaying the properties.
3880 * This is fixed in Win2k. admin/non-admin
3881 * connections both display changes immediately.
3886 result=update_a_printer_2(printer->info_2);
3891 result=WERR_UNKNOWN_LEVEL;
3898 /****************************************************************************
3899 Initialize printer devmode & data with previously saved driver init values.
3900 ****************************************************************************/
3902 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3906 TDB_DATA kbuf, dbuf;
3907 NT_PRINTER_INFO_LEVEL_2 info;
3913 * Delete any printer data 'values' already set. When called for driver
3914 * replace, there will generally be some, but during an add printer, there
3915 * should not be any (if there are delete them).
3918 if ( info_ptr->data )
3919 delete_all_printer_data( info_ptr, "" );
3921 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3924 kbuf.dsize = strlen(key)+1;
3926 dbuf = tdb_fetch(tdb_drivers, kbuf);
3929 * When changing to a driver that has no init info in the tdb, remove
3930 * the previous drivers init info and leave the new on blank.
3932 free_nt_devicemode(&info_ptr->devmode);
3937 * Get the saved DEVMODE..
3940 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3943 * The saved DEVMODE contains the devicename from the printer used during
3944 * the initialization save. Change it to reflect the new printer.
3947 if ( info.devmode ) {
3948 ZERO_STRUCT(info.devmode->devicename);
3949 fstrcpy(info.devmode->devicename, info_ptr->printername);
3953 * NT/2k does not change out the entire DeviceMode of a printer
3954 * when changing the driver. Only the driverextra, private, &
3955 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3957 * Later examination revealed that Windows NT/2k does reset the
3958 * the printer's device mode, bit **only** when you change a
3959 * property of the device mode such as the page orientation.
3964 /* Bind the saved DEVMODE to the new the printer */
3966 free_nt_devicemode(&info_ptr->devmode);
3967 info_ptr->devmode = info.devmode;
3969 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3970 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3972 /* Add the printer data 'values' to the new printer */
3974 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
3975 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3979 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3982 SAFE_FREE(dbuf.dptr);
3987 /****************************************************************************
3988 Initialize printer devmode & data with previously saved driver init values.
3989 When a printer is created using AddPrinter, the drivername bound to the
3990 printer is used to lookup previously saved driver initialization info, which
3991 is bound to the new printer.
3992 ****************************************************************************/
3994 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3996 BOOL result = False;
4000 result = set_driver_init_2(printer->info_2);
4004 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4012 /****************************************************************************
4013 Delete driver init data stored for a specified driver
4014 ****************************************************************************/
4016 BOOL del_driver_init(char *drivername)
4021 if (!drivername || !*drivername) {
4022 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4026 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4029 kbuf.dsize = strlen(key)+1;
4031 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4033 return (tdb_delete(tdb_drivers, kbuf) == 0);
4036 /****************************************************************************
4037 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4038 in the tdb. Note: this is different from the driver entry and the printer
4039 entry. There should be a single driver init entry for each driver regardless
4040 of whether it was installed from NT or 2K. Technically, they should be
4041 different, but they work out to the same struct.
4042 ****************************************************************************/
4044 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4048 int buflen, len, ret;
4049 TDB_DATA kbuf, dbuf;
4056 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4058 len += pack_values( info->data, buf+len, buflen-len );
4061 buf = (char *)SMB_REALLOC(buf, len);
4063 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4071 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4074 kbuf.dsize = strlen(key)+1;
4078 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4082 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4086 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4087 info->sharename, info->drivername));
4092 /****************************************************************************
4093 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4094 ****************************************************************************/
4096 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4100 dump_a_printer(printer, level);
4104 result = update_driver_init_2(printer->info_2);
4114 /****************************************************************************
4115 Convert the printer data value, a REG_BINARY array, into an initialization
4116 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4117 got to keep the endians happy :).
4118 ****************************************************************************/
4120 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4122 BOOL result = False;
4126 ZERO_STRUCT(devmode);
4128 prs_init(&ps, 0, ctx, UNMARSHALL);
4129 ps.data_p = (char *)data;
4130 ps.buffer_size = data_len;
4132 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4133 result = convert_devicemode("", &devmode, &nt_devmode);
4135 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4140 /****************************************************************************
4141 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4143 1. Use the driver's config DLL to this UNC printername and:
4144 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4145 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4146 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4148 The last step triggers saving the "driver initialization" information for
4149 this printer into the tdb. Later, new printers that use this driver will
4150 have this initialization information bound to them. This simulates the
4151 driver initialization, as if it had run on the Samba server (as it would
4154 The Win32 client side code requirement sucks! But until we can run arbitrary
4155 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4157 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4158 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4159 about it and you will realize why. JRR 010720
4160 ****************************************************************************/
4162 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4164 WERROR status = WERR_OK;
4165 TALLOC_CTX *ctx = NULL;
4166 NT_DEVICEMODE *nt_devmode = NULL;
4167 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4170 * When the DEVMODE is already set on the printer, don't try to unpack it.
4172 DEBUG(8,("save_driver_init_2: Enter...\n"));
4174 if ( !printer->info_2->devmode && data_len ) {
4176 * Set devmode on printer info, so entire printer initialization can be
4180 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4183 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4184 status = WERR_NOMEM;
4188 ZERO_STRUCTP(nt_devmode);
4191 * The DEVMODE is held in the 'data' component of the param in raw binary.
4192 * Convert it to to a devmode structure
4194 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4195 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4196 status = WERR_INVALID_PARAM;
4200 printer->info_2->devmode = nt_devmode;
4204 * Pack up and add (or update) the DEVMODE and any current printer data to
4205 * a 'driver init' element in the tdb
4209 if ( update_driver_init(printer, 2) != 0 ) {
4210 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4211 status = WERR_NOMEM;
4216 * If driver initialization info was successfully saved, set the current
4217 * printer to match it. This allows initialization of the current printer
4218 * as well as the driver.
4220 status = mod_a_printer(printer, 2);
4221 if (!W_ERROR_IS_OK(status)) {
4222 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4223 printer->info_2->printername));
4227 talloc_destroy(ctx);
4228 free_nt_devicemode( &nt_devmode );
4230 printer->info_2->devmode = tmp_devmode;
4235 /****************************************************************************
4236 Update the driver init info (DEVMODE and specifics) for a printer
4237 ****************************************************************************/
4239 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4241 WERROR status = WERR_OK;
4245 status = save_driver_init_2( printer, data, data_len );
4248 status = WERR_UNKNOWN_LEVEL;
4255 /****************************************************************************
4256 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4258 Previously the code had a memory allocation problem because it always
4259 used the TALLOC_CTX from the Printer_entry*. This context lasts
4260 as a long as the original handle is open. So if the client made a lot
4261 of getprinter[data]() calls, the memory usage would climb. Now we use
4262 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4263 still use the Printer_entry->ctx for maintaining the cache copy though
4264 since that object must live as long as the handle by definition.
4267 ****************************************************************************/
4269 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4270 const char *sharename)
4275 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4277 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4278 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4284 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4285 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4286 TALLOC_FREE( *pp_printer );
4291 fstrcpy( servername, print_hnd->servername );
4293 fstrcpy( servername, "%L" );
4294 standard_sub_basic( "", servername, sizeof(servername)-1 );
4297 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4300 /* we have a new printer now. Save it with this handle */
4302 if ( !W_ERROR_IS_OK(result) ) {
4303 TALLOC_FREE( *pp_printer );
4304 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4305 sharename, (unsigned int)level, dos_errstr(result)));
4309 dump_a_printer( *pp_printer, level);
4314 TALLOC_FREE( *pp_printer );
4315 return WERR_UNKNOWN_LEVEL;
4321 /****************************************************************************
4322 Deletes a NT_PRINTER_INFO_LEVEL struct.
4323 ****************************************************************************/
4325 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4327 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4334 if ( printer->info_2 )
4335 free_nt_printer_info_level_2(&printer->info_2);
4339 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4343 TALLOC_FREE(*pp_printer);
4348 /****************************************************************************
4349 ****************************************************************************/
4350 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4353 DEBUG(104,("adding a printer at level [%d]\n", level));
4354 dump_a_printer_driver(driver, level);
4358 result=add_a_printer_driver_3(driver.info_3);
4362 result=add_a_printer_driver_6(driver.info_6);
4372 /****************************************************************************
4373 ****************************************************************************/
4375 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4376 fstring drivername, const char *architecture, uint32 version)
4382 /* Sometime we just want any version of the driver */
4384 if ( version == DRIVER_ANY_VERSION ) {
4385 /* look for Win2k first and then for NT4 */
4386 result = get_a_printer_driver_3(&driver->info_3, drivername,
4389 if ( !W_ERROR_IS_OK(result) ) {
4390 result = get_a_printer_driver_3( &driver->info_3,
4391 drivername, architecture, 2 );
4394 result = get_a_printer_driver_3(&driver->info_3, drivername,
4395 architecture, version);
4404 if (W_ERROR_IS_OK(result))
4405 dump_a_printer_driver(*driver, level);
4410 /****************************************************************************
4411 ****************************************************************************/
4412 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4419 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4420 if (driver.info_3 != NULL)
4422 info3=driver.info_3;
4423 SAFE_FREE(info3->dependentfiles);
4424 ZERO_STRUCTP(info3);
4434 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4435 if (driver.info_6 != NULL) {
4436 info6=driver.info_6;
4437 SAFE_FREE(info6->dependentfiles);
4438 SAFE_FREE(info6->previousnames);
4439 ZERO_STRUCTP(info6);
4455 /****************************************************************************
4456 Determine whether or not a particular driver is currently assigned
4458 ****************************************************************************/
4460 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4463 int n_services = lp_numservices();
4464 NT_PRINTER_INFO_LEVEL *printer = NULL;
4465 BOOL in_use = False;
4470 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4472 /* loop through the printers.tdb and check for the drivername */
4474 for (snum=0; snum<n_services && !in_use; snum++) {
4475 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4478 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4481 if ( strequal(info_3->name, printer->info_2->drivername) )
4484 free_a_printer( &printer, 2 );
4487 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4490 NT_PRINTER_DRIVER_INFO_LEVEL d;
4493 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4495 /* we can still remove the driver if there is one of
4496 "Windows NT x86" version 2 or 3 left */
4498 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4499 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4502 switch ( info_3->cversion ) {
4504 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4507 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4510 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4512 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4517 /* now check the error code */
4519 if ( W_ERROR_IS_OK(werr) ) {
4520 /* it's ok to remove the driver, we have other architctures left */
4522 free_a_printer_driver( d, 3 );
4526 /* report that the driver is not in use by default */
4532 /**********************************************************************
4533 Check to see if a ogiven file is in use by *info
4534 *********************************************************************/
4536 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4543 if ( strequal(file, info->driverpath) )
4546 if ( strequal(file, info->datafile) )
4549 if ( strequal(file, info->configfile) )
4552 if ( strequal(file, info->helpfile) )
4555 /* see of there are any dependent files to examine */
4557 if ( !info->dependentfiles )
4560 while ( *info->dependentfiles[i] ) {
4561 if ( strequal(file, info->dependentfiles[i]) )
4570 /**********************************************************************
4571 Utility function to remove the dependent file pointed to by the
4572 input parameter from the list
4573 *********************************************************************/
4575 static void trim_dependent_file( fstring files[], int idx )
4578 /* bump everything down a slot */
4580 while( *files[idx+1] ) {
4581 fstrcpy( files[idx], files[idx+1] );
4590 /**********************************************************************
4591 Check if any of the files used by src are also used by drv
4592 *********************************************************************/
4594 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4595 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4597 BOOL in_use = False;
4603 /* check each file. Remove it from the src structure if it overlaps */
4605 if ( drv_file_in_use(src->driverpath, drv) ) {
4607 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4608 fstrcpy( src->driverpath, "" );
4611 if ( drv_file_in_use(src->datafile, drv) ) {
4613 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4614 fstrcpy( src->datafile, "" );
4617 if ( drv_file_in_use(src->configfile, drv) ) {
4619 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4620 fstrcpy( src->configfile, "" );
4623 if ( drv_file_in_use(src->helpfile, drv) ) {
4625 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4626 fstrcpy( src->helpfile, "" );
4629 /* are there any dependentfiles to examine? */
4631 if ( !src->dependentfiles )
4634 while ( *src->dependentfiles[i] ) {
4635 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4637 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4638 trim_dependent_file( src->dependentfiles, i );
4646 /****************************************************************************
4647 Determine whether or not a particular driver files are currently being
4648 used by any other driver.
4650 Return value is True if any files were in use by other drivers
4651 and False otherwise.
4653 Upon return, *info has been modified to only contain the driver files
4654 which are not in use
4655 ****************************************************************************/
4657 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4662 fstring *list = NULL;
4663 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4668 version = info->cversion;
4670 /* loop over all driver versions */
4672 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4674 /* get the list of drivers */
4677 ndrivers = get_ntdrivers(&list, info->environment, version);
4679 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4680 ndrivers, info->environment, version));
4682 /* check each driver for overlap in files */
4684 for (i=0; i<ndrivers; i++) {
4685 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4687 ZERO_STRUCT(driver);
4689 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4694 /* check if d2 uses any files from d1 */
4695 /* only if this is a different driver than the one being deleted */
4697 if ( !strequal(info->name, driver.info_3->name) ) {
4698 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4699 free_a_printer_driver(driver, 3);
4705 free_a_printer_driver(driver, 3);
4710 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4712 driver.info_3 = info;
4714 if ( DEBUGLEVEL >= 20 )
4715 dump_a_printer_driver( driver, 3 );
4720 /****************************************************************************
4721 Actually delete the driver files. Make sure that
4722 printer_driver_files_in_use() return False before calling
4724 ****************************************************************************/
4726 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4731 connection_struct *conn;
4741 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4744 * Connect to the print$ share under the same account as the
4745 * user connected to the rpc pipe. Note we must be root to
4749 null_pw = data_blob( NULL, 0 );
4750 fstrcpy(res_type, "A:");
4752 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4756 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4760 if ( !CAN_WRITE(conn) ) {
4761 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4765 /* Save who we are - we are temporarily becoming the connection user. */
4767 if ( !become_user(conn, conn->vuid) ) {
4768 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4772 /* now delete the files; must strip the '\print$' string from
4775 if ( *info_3->driverpath ) {
4776 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4778 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4779 DEBUG(10,("deleting driverfile [%s]\n", s));
4780 unlink_internals(conn, 0, file, False);
4784 if ( *info_3->configfile ) {
4785 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4787 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4788 DEBUG(10,("deleting configfile [%s]\n", s));
4789 unlink_internals(conn, 0, file, False);
4793 if ( *info_3->datafile ) {
4794 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4796 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4797 DEBUG(10,("deleting datafile [%s]\n", s));
4798 unlink_internals(conn, 0, file, False);
4802 if ( *info_3->helpfile ) {
4803 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4805 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4806 DEBUG(10,("deleting helpfile [%s]\n", s));
4807 unlink_internals(conn, 0, file, False);
4811 /* check if we are done removing files */
4813 if ( info_3->dependentfiles ) {
4814 while ( info_3->dependentfiles[i][0] ) {
4817 /* bypass the "\print$" portion of the path */
4819 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4821 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4822 DEBUG(10,("deleting dependent file [%s]\n", file));
4823 unlink_internals(conn, 0, file, False);
4835 /****************************************************************************
4836 Remove a printer driver from the TDB. This assumes that the the driver was
4837 previously looked up.
4838 ***************************************************************************/
4840 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4841 uint32 version, BOOL delete_files )
4845 TDB_DATA kbuf, dbuf;
4846 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4848 /* delete the tdb data first */
4850 arch = get_short_archi(info_3->environment);
4851 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4852 arch, version, info_3->name);
4854 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4855 key, delete_files ? "TRUE" : "FALSE" ));
4857 ctr.info_3 = info_3;
4858 dump_a_printer_driver( ctr, 3 );
4861 kbuf.dsize=strlen(key)+1;
4863 /* check if the driver actually exists for this environment */
4865 dbuf = tdb_fetch( tdb_drivers, kbuf );
4867 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4868 return WERR_UNKNOWN_PRINTER_DRIVER;
4871 SAFE_FREE( dbuf.dptr );
4873 /* ok... the driver exists so the delete should return success */
4875 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4876 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4877 return WERR_ACCESS_DENIED;
4881 * now delete any associated files if delete_files == True
4882 * even if this part failes, we return succes because the
4883 * driver doesn not exist any more
4887 delete_driver_files( info_3, user );
4890 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4895 /****************************************************************************
4896 Store a security desc for a printer.
4897 ****************************************************************************/
4899 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4901 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4902 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4904 TALLOC_CTX *mem_ctx = NULL;
4908 mem_ctx = talloc_init("nt_printing_setsec");
4909 if (mem_ctx == NULL)
4912 /* The old owner and group sids of the security descriptor are not
4913 present when new ACEs are added or removed by changing printer
4914 permissions through NT. If they are NULL in the new security
4915 descriptor then copy them over from the old one. */
4917 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4918 DOM_SID *owner_sid, *group_sid;
4919 SEC_ACL *dacl, *sacl;
4920 SEC_DESC *psd = NULL;
4923 nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr);
4925 /* Pick out correct owner and group sids */
4927 owner_sid = secdesc_ctr->sec->owner_sid ?
4928 secdesc_ctr->sec->owner_sid :
4929 old_secdesc_ctr->sec->owner_sid;
4931 group_sid = secdesc_ctr->sec->grp_sid ?
4932 secdesc_ctr->sec->grp_sid :
4933 old_secdesc_ctr->sec->grp_sid;
4935 dacl = secdesc_ctr->sec->dacl ?
4936 secdesc_ctr->sec->dacl :
4937 old_secdesc_ctr->sec->dacl;
4939 sacl = secdesc_ctr->sec->sacl ?
4940 secdesc_ctr->sec->sacl :
4941 old_secdesc_ctr->sec->sacl;
4943 /* Make a deep copy of the security descriptor */
4945 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4946 owner_sid, group_sid,
4951 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4954 if (!new_secdesc_ctr) {
4955 new_secdesc_ctr = secdesc_ctr;
4958 /* Store the security descriptor in a tdb */
4960 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4961 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4963 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4965 status = WERR_BADFUNC;
4969 key = make_printers_secdesc_tdbkey( sharename );
4971 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4974 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
4975 status = WERR_BADFUNC;
4978 /* Free malloc'ed memory */
4984 talloc_destroy(mem_ctx);
4988 /****************************************************************************
4989 Construct a default security descriptor buffer for a printer.
4990 ****************************************************************************/
4992 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4994 SEC_ACE ace[5]; /* max number of ace entries */
4997 SEC_ACL *psa = NULL;
4998 SEC_DESC_BUF *sdb = NULL;
4999 SEC_DESC *psd = NULL;
5003 /* Create an ACE where Everyone is allowed to print */
5005 init_sec_access(&sa, PRINTER_ACE_PRINT);
5006 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5007 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5009 /* Add the domain admins group if we are a DC */
5012 DOM_SID domadmins_sid;
5014 sid_copy(&domadmins_sid, get_global_sam_sid());
5015 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5017 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5018 init_sec_ace(&ace[i++], &domadmins_sid,
5019 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5020 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5021 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5022 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5024 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5025 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5027 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5028 init_sec_ace(&ace[i++], &adm_sid,
5029 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5030 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5031 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5032 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5035 /* add BUILTIN\Administrators as FULL CONTROL */
5037 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5038 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5039 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5040 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5041 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5042 SEC_ACE_TYPE_ACCESS_ALLOWED,
5043 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5045 /* Make the security descriptor owned by the BUILTIN\Administrators */
5047 /* The ACL revision number in rpc_secdesc.h differs from the one
5048 created by NT when setting ACE entries in printer
5049 descriptors. NT4 complains about the property being edited by a
5052 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5053 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5054 &global_sid_Builtin_Administrators,
5055 &global_sid_Builtin_Administrators,
5056 NULL, psa, &sd_size);
5060 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5064 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5066 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5067 (unsigned int)sd_size));
5072 /****************************************************************************
5073 Get a security desc for a printer.
5074 ****************************************************************************/
5076 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5082 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5083 sharename = temp + 1;
5086 /* Fetch security descriptor from tdb */
5088 key = make_printers_secdesc_tdbkey( sharename );
5090 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5091 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5093 DEBUG(4,("using default secdesc for %s\n", sharename));
5095 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5099 /* Save default security descriptor for later */
5101 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5102 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5104 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5105 tdb_prs_store(tdb_printers, key, &ps);
5112 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5113 this security descriptor has been created when winbindd was
5114 down. Take ownership of security descriptor. */
5116 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5119 /* Change sd owner to workgroup administrator */
5121 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5122 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5123 SEC_DESC *psd = NULL;
5128 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5130 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5132 (*secdesc_ctr)->sec->grp_sid,
5133 (*secdesc_ctr)->sec->sacl,
5134 (*secdesc_ctr)->sec->dacl,
5137 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5139 /* Swap with other one */
5141 *secdesc_ctr = new_secdesc_ctr;
5145 nt_printing_setsec(sharename, *secdesc_ctr);
5149 if (DEBUGLEVEL >= 10) {
5150 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5153 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5154 sharename, the_acl->num_aces));
5156 for (i = 0; i < the_acl->num_aces; i++) {
5159 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5161 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5162 the_acl->ace[i].type, the_acl->ace[i].flags,
5163 the_acl->ace[i].info.mask));
5173 1: level not implemented
5174 2: file doesn't exist
5175 3: can't allocate memory
5176 4: can't free memory
5177 5: non existant struct
5181 A printer and a printer driver are 2 different things.
5182 NT manages them separatelly, Samba does the same.
5183 Why ? Simply because it's easier and it makes sense !
5185 Now explanation: You have 3 printers behind your samba server,
5186 2 of them are the same make and model (laser A and B). But laser B
5187 has an 3000 sheet feeder and laser A doesn't such an option.
5188 Your third printer is an old dot-matrix model for the accounting :-).
5190 If the /usr/local/samba/lib directory (default dir), you will have
5191 5 files to describe all of this.
5193 3 files for the printers (1 by printer):
5196 NTprinter_accounting
5197 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5198 NTdriver_printer model X
5199 NTdriver_printer model Y
5201 jfm: I should use this comment for the text file to explain
5202 same thing for the forms BTW.
5203 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5207 /* Convert generic access rights to printer object specific access rights.
5208 It turns out that NT4 security descriptors use generic access rights and
5209 NT5 the object specific ones. */
5211 void map_printer_permissions(SEC_DESC *sd)
5215 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5216 se_map_generic(&sd->dacl->ace[i].info.mask,
5217 &printer_generic_mapping);
5221 /****************************************************************************
5222 Check a user has permissions to perform the given operation. We use the
5223 permission constants defined in include/rpc_spoolss.h to check the various
5224 actions we perform when checking printer access.
5226 PRINTER_ACCESS_ADMINISTER:
5227 print_queue_pause, print_queue_resume, update_printer_sec,
5228 update_printer, spoolss_addprinterex_level_2,
5229 _spoolss_setprinterdata
5234 JOB_ACCESS_ADMINISTER:
5235 print_job_delete, print_job_pause, print_job_resume,
5238 Try access control in the following order (for performance reasons):
5239 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5240 2) check security descriptor (bit comparisons in memory)
5241 3) "printer admins" (may result in numerous calls to winbind)
5243 ****************************************************************************/
5244 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5246 SEC_DESC_BUF *secdesc = NULL;
5247 uint32 access_granted;
5251 TALLOC_CTX *mem_ctx = NULL;
5252 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5254 /* If user is NULL then use the current_user structure */
5257 user = ¤t_user;
5259 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5261 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5265 /* Get printer name */
5267 pname = PRINTERNAME(snum);
5269 if (!pname || !*pname) {
5274 /* Get printer security descriptor */
5276 if(!(mem_ctx = talloc_init("print_access_check"))) {
5281 nt_printing_getsec(mem_ctx, pname, &secdesc);
5283 if (access_type == JOB_ACCESS_ADMINISTER) {
5284 SEC_DESC_BUF *parent_secdesc = secdesc;
5286 /* Create a child security descriptor to check permissions
5287 against. This is because print jobs are child objects
5288 objects of a printer. */
5290 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5292 /* Now this is the bit that really confuses me. The access
5293 type needs to be changed from JOB_ACCESS_ADMINISTER to
5294 PRINTER_ACCESS_ADMINISTER for this to work. Something
5295 to do with the child (job) object becoming like a
5298 access_type = PRINTER_ACCESS_ADMINISTER;
5303 map_printer_permissions(secdesc->sec);
5305 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5306 &access_granted, &status);
5308 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5310 /* see if we need to try the printer admin list */
5312 if ((access_granted == 0) &&
5313 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5314 user->nt_user_token,
5315 lp_printer_admin(snum)))) {
5319 talloc_destroy(mem_ctx);
5327 /****************************************************************************
5328 Check the time parameters allow a print operation.
5329 *****************************************************************************/
5331 BOOL print_time_access_check(int snum)
5333 NT_PRINTER_INFO_LEVEL *printer = NULL;
5335 time_t now = time(NULL);
5339 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5342 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5346 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5348 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5351 free_a_printer(&printer, 2);
5359 /****************************************************************************
5360 Fill in the servername sent in the _spoolss_open_printer_ex() call
5361 ****************************************************************************/
5363 char* get_server_name( Printer_entry *printer )
5365 return printer->servername;