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-2003.
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 */
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
45 /* Map generic permissions to printer object specific permissions */
47 GENERIC_MAPPING printer_generic_mapping = {
54 STANDARD_MAPPING printer_std_mapping = {
61 /* Map generic permissions to print server object specific permissions */
63 GENERIC_MAPPING printserver_generic_mapping = {
70 STANDARD_MAPPING printserver_std_mapping = {
77 /* We need one default form to support our default printer. Msoft adds the
78 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
79 array index). Letter is always first, so (for the current code) additions
80 always put things in the correct order. */
81 static const nt_forms_struct default_forms[] = {
82 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
84 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
85 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
86 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
87 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
88 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
89 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
90 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
92 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
93 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
94 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
95 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
96 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
97 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
98 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
99 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
100 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
101 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
102 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
103 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
104 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
105 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
106 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
107 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
108 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
109 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
110 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
111 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
112 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
113 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
114 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
115 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
116 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
117 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
118 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
119 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
120 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
121 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
122 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
123 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
125 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
126 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
127 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
128 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
129 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
131 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
132 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
133 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
134 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
135 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
136 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
137 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
139 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
140 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
141 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
142 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
143 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
144 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
145 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
146 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
147 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
148 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
149 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
151 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
152 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
153 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
154 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
155 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
156 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
157 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
158 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
159 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
160 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
161 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
162 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
163 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
164 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
165 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
166 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
167 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
168 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
169 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
170 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
171 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
172 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
173 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
174 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
175 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
176 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
177 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
178 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
179 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
180 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
181 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
182 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
183 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
184 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
185 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
186 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
187 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
188 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
189 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
190 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
191 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
192 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
193 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
194 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
195 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
196 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
197 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
198 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
199 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
203 const char *long_archi;
204 const char *short_archi;
208 #define SPL_ARCH_WIN40 "WIN40"
209 #define SPL_ARCH_W32X86 "W32X86"
210 #define SPL_ARCH_W32MIPS "W32MIPS"
211 #define SPL_ARCH_W32ALPHA "W32ALPHA"
212 #define SPL_ARCH_W32PPC "W32PPC"
213 #define SPL_ARCH_IA64 "IA64"
214 #define SPL_ARCH_X64 "x64"
216 static const struct table_node archi_table[]= {
218 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
219 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
220 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
221 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
222 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
223 {"Windows IA64", SPL_ARCH_IA64, 3 },
224 {"Windows x64", SPL_ARCH_X64, 3 },
228 static BOOL upgrade_to_version_3(void)
230 TDB_DATA kbuf, newkey, dbuf;
232 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
234 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
235 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
237 dbuf = tdb_fetch(tdb_drivers, kbuf);
239 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
240 DEBUG(0,("upgrade_to_version_3:moving form\n"));
241 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
246 if (tdb_delete(tdb_drivers, kbuf) != 0) {
247 SAFE_FREE(dbuf.dptr);
248 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
253 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
254 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
255 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
260 if (tdb_delete(tdb_drivers, kbuf) != 0) {
261 SAFE_FREE(dbuf.dptr);
262 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
267 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
268 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
269 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
274 if (tdb_delete(tdb_drivers, kbuf) != 0) {
275 SAFE_FREE(dbuf.dptr);
276 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
281 SAFE_FREE(dbuf.dptr);
287 /*******************************************************************
288 Fix an issue with security descriptors. Printer sec_desc must
289 use more than the generic bits that were previously used
290 in <= 3.0.14a. They must also have a owner and group SID assigned.
291 Otherwise, any printers than have been migrated to a Windows
292 host using printmig.exe will not be accessible.
293 *******************************************************************/
295 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
296 TDB_DATA data, void *state )
299 SEC_DESC_BUF *sd_orig = NULL;
300 SEC_DESC_BUF *sd_new, *sd_store;
301 SEC_DESC *sec, *new_sec;
302 TALLOC_CTX *ctx = state;
304 uint32 sd_size, size_new_sec;
307 if (!data.dptr || data.dsize == 0)
310 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
313 /* upgrade the security descriptor */
317 prs_init( &ps, 0, ctx, UNMARSHALL );
318 prs_give_memory( &ps, data.dptr, data.dsize, True );
320 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
321 /* delete bad entries */
322 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
323 tdb_delete( tdb_printers, key );
329 /* is this even valid? */
334 /* update access masks */
336 for ( i=0; i<sec->dacl->num_aces; i++ ) {
337 switch ( sec->dacl->ace[i].info.mask ) {
338 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
339 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
342 case GENERIC_ALL_ACCESS:
343 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
346 case READ_CONTROL_ACCESS:
347 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
349 default: /* no change */
354 /* create a new SEC_DESC with the appropriate owner and group SIDs */
356 string_to_sid(&sid, "S-1-5-32-544" );
357 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION,
359 NULL, NULL, &size_new_sec );
360 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
362 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
363 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
369 sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
370 prs_init(&ps, sd_size, ctx, MARSHALL);
372 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
373 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
377 data.dptr = prs_data_p( &ps );
378 data.dsize = sd_size;
380 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
384 /* 0 to continue and non-zero to stop traversal */
386 return (result == -1);
389 /*******************************************************************
390 *******************************************************************/
392 static BOOL upgrade_to_version_4(void)
397 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
399 if ( !(ctx = talloc_init_named( "upgrade_to_version_4" )) )
402 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
404 talloc_destroy( ctx );
406 return ( result != -1 );
409 /****************************************************************************
410 Open the NT printing tdbs. Done once before fork().
411 ****************************************************************************/
413 BOOL nt_printing_init(void)
415 static pid_t local_pid;
416 const char *vstring = "INFO/version";
419 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
423 tdb_close(tdb_drivers);
424 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
426 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
427 lock_path("ntdrivers.tdb"), strerror(errno) ));
432 tdb_close(tdb_printers);
433 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
435 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
436 lock_path("ntprinters.tdb"), strerror(errno) ));
441 tdb_close(tdb_forms);
442 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
444 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
445 lock_path("ntforms.tdb"), strerror(errno) ));
449 local_pid = sys_getpid();
451 /* handle a Samba upgrade */
452 tdb_lock_bystring(tdb_drivers, vstring, 0);
454 /* ---------------- Start Lock Region ---------------- */
456 /* Cope with byte-reversed older versions of the db. */
457 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
459 if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
461 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
462 /* Written on a bigendian machine with old fetch_int code. Save as le. */
463 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
464 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
465 vers_id = NTDRIVERS_DATABASE_VERSION_3;
468 if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
470 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
471 if (!upgrade_to_version_3())
474 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
476 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
479 /* at this point we know that the database is at version 3 so upgrade to v4 */
481 if ( !upgrade_to_version_4() )
483 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
486 /* ---------------- End Lock Region ------------------ */
488 tdb_unlock_bystring(tdb_drivers, vstring);
490 update_c_setprinter(True);
493 * register callback to handle updating printers as new
494 * drivers are installed
497 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
500 * register callback to handle updating printer data
501 * when a driver is initialized
504 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
507 * register callback to handle invalidating the printer cache
508 * between smbd processes.
511 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
513 /* of course, none of the message callbacks matter if you don't
514 tell messages.c that you interested in receiving PRINT_GENERAL
515 msgs. This is done in claim_connection() */
518 if ( lp_security() == SEC_ADS ) {
519 win_rc = check_published_printers();
520 if (!W_ERROR_IS_OK(win_rc))
521 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
527 /*******************************************************************
528 Function to allow filename parsing "the old way".
529 ********************************************************************/
531 static BOOL driver_unix_convert(char *name,connection_struct *conn,
532 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
535 unix_clean_name(name);
536 trim_string(name,"/","/");
537 return unix_convert(name, conn, saved_last_component, bad_path, pst);
540 /*******************************************************************
541 tdb traversal function for counting printers.
542 ********************************************************************/
544 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
545 TDB_DATA data, void *context)
547 int *printer_count = (int*)context;
549 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
551 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
557 /*******************************************************************
558 Update the spooler global c_setprinter. This variable is initialized
559 when the parent smbd starts with the number of existing printers. It
560 is monotonically increased by the current number of printers *after*
561 each add or delete printer RPC. Only Microsoft knows why... JRR020119
562 ********************************************************************/
564 uint32 update_c_setprinter(BOOL initialize)
567 int32 printer_count = 0;
569 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
571 /* Traverse the tdb, counting the printers */
572 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
574 /* If initializing, set c_setprinter to current printers count
575 * otherwise, bump it by the current printer count
578 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
580 c_setprinter = printer_count;
582 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
583 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
585 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
587 return (uint32)c_setprinter;
590 /*******************************************************************
591 Get the spooler global c_setprinter, accounting for initialization.
592 ********************************************************************/
594 uint32 get_c_setprinter(void)
596 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
598 if (c_setprinter == (int32)-1)
599 c_setprinter = update_c_setprinter(True);
601 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
603 return (uint32)c_setprinter;
606 /****************************************************************************
607 Get builtin form struct list.
608 ****************************************************************************/
610 int get_builtin_ntforms(nt_forms_struct **list)
612 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
613 return sizeof(default_forms) / sizeof(default_forms[0]);
616 /****************************************************************************
617 get a builtin form struct
618 ****************************************************************************/
620 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
624 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
625 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
626 count = sizeof(default_forms) / sizeof(default_forms[0]);
627 for (i=0;i<count;i++) {
628 if (strequal(form_name,default_forms[i].name)) {
629 DEBUGADD(6,("Found builtin form %s \n", form_name));
630 memcpy(form,&default_forms[i],sizeof(*form));
638 /****************************************************************************
639 get a form struct list
640 ****************************************************************************/
641 int get_ntforms(nt_forms_struct **list)
643 TDB_DATA kbuf, newkey, dbuf;
645 nt_forms_struct form;
650 for (kbuf = tdb_firstkey(tdb_forms);
652 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
654 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
657 dbuf = tdb_fetch(tdb_forms, kbuf);
661 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
662 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
663 &i, &form.flag, &form.width, &form.length, &form.left,
664 &form.top, &form.right, &form.bottom);
665 SAFE_FREE(dbuf.dptr);
666 if (ret != dbuf.dsize)
669 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
671 DEBUG(0,("get_ntforms: Realloc fail.\n"));
683 /****************************************************************************
684 write a form struct list
685 ****************************************************************************/
686 int write_ntforms(nt_forms_struct **list, int number)
693 for (i=0;i<number;i++) {
694 /* save index, so list is rebuilt in correct order */
695 len = tdb_pack(buf, sizeof(buf), "dddddddd",
696 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
697 (*list)[i].left, (*list)[i].top, (*list)[i].right,
699 if (len > sizeof(buf)) break;
700 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
701 kbuf.dsize = strlen(key)+1;
705 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
711 /****************************************************************************
712 add a form struct at the end of the list
713 ****************************************************************************/
714 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
722 * NT tries to add forms even when
723 * they are already in the base
724 * only update the values if already present
729 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
730 for (n=0; n<*count; n++) {
731 if ( strequal((*list)[n].name, form_name) ) {
738 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
739 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
743 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
747 (*list)[n].flag=form->flags;
748 (*list)[n].width=form->size_x;
749 (*list)[n].length=form->size_y;
750 (*list)[n].left=form->left;
751 (*list)[n].top=form->top;
752 (*list)[n].right=form->right;
753 (*list)[n].bottom=form->bottom;
755 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
756 update ? "updated" : "added", form_name));
761 /****************************************************************************
762 Delete a named form struct.
763 ****************************************************************************/
765 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
774 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
776 for (n=0; n<*count; n++) {
777 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
778 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
784 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
785 *ret = WERR_INVALID_PARAM;
789 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
790 kbuf.dsize = strlen(key)+1;
792 if (tdb_delete(tdb_forms, kbuf) != 0) {
800 /****************************************************************************
801 Update a form struct.
802 ****************************************************************************/
804 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
808 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
810 DEBUG(106, ("[%s]\n", form_name));
811 for (n=0; n<count; n++) {
812 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
813 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
817 if (n==count) return;
819 (*list)[n].flag=form->flags;
820 (*list)[n].width=form->size_x;
821 (*list)[n].length=form->size_y;
822 (*list)[n].left=form->left;
823 (*list)[n].top=form->top;
824 (*list)[n].right=form->right;
825 (*list)[n].bottom=form->bottom;
828 /****************************************************************************
829 Get the nt drivers list.
830 Traverse the database and look-up the matching names.
831 ****************************************************************************/
832 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
835 const char *short_archi;
838 TDB_DATA kbuf, newkey;
840 short_archi = get_short_archi(architecture);
841 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
843 for (kbuf = tdb_firstkey(tdb_drivers);
845 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
847 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
850 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
851 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
856 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
863 /****************************************************************************
864 function to do the mapping between the long architecture name and
866 ****************************************************************************/
867 const char *get_short_archi(const char *long_archi)
871 DEBUG(107,("Getting architecture dependant directory\n"));
874 } while ( (archi_table[i].long_archi!=NULL ) &&
875 StrCaseCmp(long_archi, archi_table[i].long_archi) );
877 if (archi_table[i].long_archi==NULL) {
878 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
882 /* this might be client code - but shouldn't this be an fstrcpy etc? */
885 DEBUGADD(108,("index: [%d]\n", i));
886 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
887 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
889 return archi_table[i].short_archi;
892 /****************************************************************************
893 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
894 There are two case to be covered here: PE (Portable Executable) and NE (New
895 Executable) files. Both files support the same INFO structure, but PE files
896 store the signature in unicode, and NE files store it as !unicode.
897 returns -1 on error, 1 on version info found, and 0 on no version info found.
898 ****************************************************************************/
900 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
906 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
907 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
908 fname, PE_HEADER_SIZE));
912 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
913 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
914 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
915 fname, (unsigned long)byte_count));
916 goto no_version_info;
919 /* Is this really a DOS header? */
920 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
921 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
922 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
923 goto no_version_info;
926 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
927 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
928 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 goto no_version_info;
934 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
935 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
936 fname, (unsigned long)byte_count));
937 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
938 goto no_version_info;
941 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
942 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
943 unsigned int num_sections;
944 unsigned int section_table_bytes;
946 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
947 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
948 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
949 /* At this point, we assume the file is in error. It still could be somthing
950 * else besides a PE file, but it unlikely at this point.
955 /* get the section table */
956 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
957 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
958 if (section_table_bytes == 0)
962 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
963 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
964 fname, section_table_bytes));
968 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
969 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
970 fname, (unsigned long)byte_count));
974 /* Iterate the section table looking for the resource section ".rsrc" */
975 for (i = 0; i < num_sections; i++) {
976 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
978 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
979 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
980 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
982 if (section_bytes == 0)
986 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
987 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
988 fname, section_bytes));
992 /* Seek to the start of the .rsrc section info */
993 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
994 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
999 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1000 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1001 fname, (unsigned long)byte_count));
1005 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1008 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1009 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1010 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1011 /* Align to next long address */
1012 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1014 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1015 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1016 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1018 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1019 fname, *major, *minor,
1020 (*major>>16)&0xffff, *major&0xffff,
1021 (*minor>>16)&0xffff, *minor&0xffff));
1030 /* Version info not found, fall back to origin date/time */
1031 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1035 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1036 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1037 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1038 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1039 /* At this point, we assume the file is in error. It still could be somthing
1040 * else besides a NE file, but it unlikely at this point. */
1044 /* Allocate a bit more space to speed up things */
1046 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1047 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1048 fname, PE_HEADER_SIZE));
1052 /* This is a HACK! I got tired of trying to sort through the messy
1053 * 'NE' file format. If anyone wants to clean this up please have at
1054 * it, but this works. 'NE' files will eventually fade away. JRR */
1055 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1056 /* Cover case that should not occur in a well formed 'NE' .dll file */
1057 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1059 for(i=0; i<byte_count; i++) {
1060 /* Fast skip past data that can't possibly match */
1061 if (buf[i] != 'V') continue;
1063 /* Potential match data crosses buf boundry, move it to beginning
1064 * of buf, and fill the buf with as much as it will hold. */
1065 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1068 memcpy(buf, &buf[i], byte_count-i);
1069 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1070 (byte_count-i))) < 0) {
1072 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1077 byte_count = bc + (byte_count - i);
1078 if (byte_count<VS_VERSION_INFO_SIZE) break;
1083 /* Check that the full signature string and the magic number that
1084 * follows exist (not a perfect solution, but the chances that this
1085 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1086 * twice, as it is simpler to read the code. */
1087 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1088 /* Compute skip alignment to next long address */
1089 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1090 sizeof(VS_SIGNATURE)) & 3;
1091 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1093 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1094 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1095 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1096 fname, *major, *minor,
1097 (*major>>16)&0xffff, *major&0xffff,
1098 (*minor>>16)&0xffff, *minor&0xffff));
1105 /* Version info not found, fall back to origin date/time */
1106 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1111 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1112 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1113 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1124 /****************************************************************************
1125 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1126 share one or more files. During the MS installation process files are checked
1127 to insure that only a newer version of a shared file is installed over an
1128 older version. There are several possibilities for this comparison. If there
1129 is no previous version, the new one is newer (obviously). If either file is
1130 missing the version info structure, compare the creation date (on Unix use
1131 the modification date). Otherwise chose the numerically larger version number.
1132 ****************************************************************************/
1134 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1136 BOOL use_version = True;
1141 time_t new_create_time;
1145 time_t old_create_time;
1149 files_struct *fsp = NULL;
1151 SMB_STRUCT_STAT stat_buf;
1155 ZERO_STRUCT(stat_buf);
1156 new_create_time = (time_t)0;
1157 old_create_time = (time_t)0;
1159 /* Get file version info (if available) for previous file (if it exists) */
1160 pstrcpy(filepath, old_file);
1162 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1164 fsp = open_file_shared(conn, filepath, &stat_buf,
1165 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1166 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1167 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1169 /* Old file not found, so by definition new file is in fact newer */
1170 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1175 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1176 if (ret == -1) goto error_exit;
1179 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1181 use_version = False;
1182 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1183 old_create_time = st.st_mtime;
1184 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1187 close_file(fsp, True);
1189 /* Get file version info (if available) for new file */
1190 pstrcpy(filepath, new_file);
1191 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1193 fsp = open_file_shared(conn, filepath, &stat_buf,
1194 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1195 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1196 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1198 /* New file not found, this shouldn't occur if the caller did its job */
1199 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1204 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1205 if (ret == -1) goto error_exit;
1208 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1210 use_version = False;
1211 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1212 new_create_time = st.st_mtime;
1213 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1216 close_file(fsp, True);
1218 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1219 /* Compare versions and choose the larger version number */
1220 if (new_major > old_major ||
1221 (new_major == old_major && new_minor > old_minor)) {
1223 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1227 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1232 /* Compare modification time/dates and choose the newest time/date */
1233 if (new_create_time > old_create_time) {
1234 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1238 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1245 close_file(fsp, True);
1249 /****************************************************************************
1250 Determine the correct cVersion associated with an architecture and driver
1251 ****************************************************************************/
1252 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1253 struct current_user *user, WERROR *perr)
1262 files_struct *fsp = NULL;
1265 connection_struct *conn;
1269 *perr = WERR_INVALID_PARAM;
1271 /* If architecture is Windows 95/98/ME, the version is always 0. */
1272 if (strcmp(architecture, "WIN40") == 0) {
1273 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1279 * Connect to the print$ share under the same account as the user connected
1280 * to the rpc pipe. Note we must still be root to do this.
1283 /* Null password is ok - we are already an authenticated user... */
1284 null_pw = data_blob(NULL, 0);
1285 fstrcpy(res_type, "A:");
1287 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1291 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1292 *perr = ntstatus_to_werror(nt_status);
1296 /* We are temporarily becoming the connection user. */
1297 if (!become_user(conn, user->vuid)) {
1298 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1299 *perr = WERR_ACCESS_DENIED;
1303 /* Open the driver file (Portable Executable format) and determine the
1304 * deriver the cversion. */
1305 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1307 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1309 fsp = open_file_shared(conn, driverpath, &st,
1310 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1311 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1312 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1314 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1315 driverpath, errno));
1316 *perr = WERR_ACCESS_DENIED;
1322 int ret = get_file_version(fsp, driverpath, &major, &minor);
1323 if (ret == -1) goto error_exit;
1326 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1331 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1332 * for more details. Version in this case is not just the version of the
1333 * file, but the version in the sense of kernal mode (2) vs. user mode
1334 * (3) drivers. Other bits of the version fields are the version info.
1337 cversion = major & 0x0000ffff;
1339 case 2: /* WinNT drivers */
1340 case 3: /* Win2K drivers */
1344 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1345 driverpath, cversion));
1349 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1350 driverpath, major, minor));
1353 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1354 driverpath, cversion));
1356 close_file(fsp, True);
1357 close_cnum(conn, user->vuid);
1366 close_file(fsp, True);
1368 close_cnum(conn, user->vuid);
1373 /****************************************************************************
1374 ****************************************************************************/
1375 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1376 struct current_user *user)
1378 const char *architecture;
1384 /* clean up the driver name.
1385 * we can get .\driver.dll
1386 * or worse c:\windows\system\driver.dll !
1388 /* using an intermediate string to not have overlaping memcpy()'s */
1389 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1390 fstrcpy(new_name, p+1);
1391 fstrcpy(driver->driverpath, new_name);
1394 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1395 fstrcpy(new_name, p+1);
1396 fstrcpy(driver->datafile, new_name);
1399 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1400 fstrcpy(new_name, p+1);
1401 fstrcpy(driver->configfile, new_name);
1404 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1405 fstrcpy(new_name, p+1);
1406 fstrcpy(driver->helpfile, new_name);
1409 if (driver->dependentfiles) {
1410 for (i=0; *driver->dependentfiles[i]; i++) {
1411 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1412 fstrcpy(new_name, p+1);
1413 fstrcpy(driver->dependentfiles[i], new_name);
1418 architecture = get_short_archi(driver->environment);
1420 /* jfm:7/16/2000 the client always sends the cversion=0.
1421 * The server should check which version the driver is by reading
1422 * the PE header of driver->driverpath.
1424 * For Windows 95/98 the version is 0 (so the value sent is correct)
1425 * For Windows NT (the architecture doesn't matter)
1426 * NT 3.1: cversion=0
1427 * NT 3.5/3.51: cversion=1
1431 if ((driver->cversion = get_correct_cversion( architecture,
1432 driver->driverpath, user, &err)) == -1)
1438 /****************************************************************************
1439 ****************************************************************************/
1440 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1442 const char *architecture;
1448 /* clean up the driver name.
1449 * we can get .\driver.dll
1450 * or worse c:\windows\system\driver.dll !
1452 /* using an intermediate string to not have overlaping memcpy()'s */
1453 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1454 fstrcpy(new_name, p+1);
1455 fstrcpy(driver->driverpath, new_name);
1458 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1459 fstrcpy(new_name, p+1);
1460 fstrcpy(driver->datafile, new_name);
1463 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1464 fstrcpy(new_name, p+1);
1465 fstrcpy(driver->configfile, new_name);
1468 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1469 fstrcpy(new_name, p+1);
1470 fstrcpy(driver->helpfile, new_name);
1473 if (driver->dependentfiles) {
1474 for (i=0; *driver->dependentfiles[i]; i++) {
1475 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1476 fstrcpy(new_name, p+1);
1477 fstrcpy(driver->dependentfiles[i], new_name);
1482 architecture = get_short_archi(driver->environment);
1484 /* jfm:7/16/2000 the client always sends the cversion=0.
1485 * The server should check which version the driver is by reading
1486 * the PE header of driver->driverpath.
1488 * For Windows 95/98 the version is 0 (so the value sent is correct)
1489 * For Windows NT (the architecture doesn't matter)
1490 * NT 3.1: cversion=0
1491 * NT 3.5/3.51: cversion=1
1495 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1501 /****************************************************************************
1502 ****************************************************************************/
1503 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1504 uint32 level, struct current_user *user)
1509 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1510 driver=driver_abstract.info_3;
1511 return clean_up_driver_struct_level_3(driver, user);
1515 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1516 driver=driver_abstract.info_6;
1517 return clean_up_driver_struct_level_6(driver, user);
1520 return WERR_INVALID_PARAM;
1524 /****************************************************************************
1525 This function sucks and should be replaced. JRA.
1526 ****************************************************************************/
1528 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1530 dst->cversion = src->version;
1532 fstrcpy( dst->name, src->name);
1533 fstrcpy( dst->environment, src->environment);
1534 fstrcpy( dst->driverpath, src->driverpath);
1535 fstrcpy( dst->datafile, src->datafile);
1536 fstrcpy( dst->configfile, src->configfile);
1537 fstrcpy( dst->helpfile, src->helpfile);
1538 fstrcpy( dst->monitorname, src->monitorname);
1539 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1540 dst->dependentfiles = src->dependentfiles;
1543 #if 0 /* Debugging function */
1545 static char* ffmt(unsigned char *c){
1547 static char ffmt_str[17];
1549 for (i=0; i<16; i++) {
1550 if ((c[i] < ' ') || (c[i] > '~'))
1561 /****************************************************************************
1562 ****************************************************************************/
1563 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1564 struct current_user *user, WERROR *perr)
1566 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1567 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1568 const char *architecture;
1573 connection_struct *conn;
1583 memset(inbuf, '\0', sizeof(inbuf));
1584 memset(outbuf, '\0', sizeof(outbuf));
1588 driver=driver_abstract.info_3;
1589 else if (level==6) {
1590 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1591 driver = &converted_driver;
1593 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1597 architecture = get_short_archi(driver->environment);
1600 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1601 * Note we must be root to do this.
1604 null_pw = data_blob(NULL, 0);
1605 fstrcpy(res_type, "A:");
1607 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1611 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1612 *perr = ntstatus_to_werror(nt_status);
1617 * Save who we are - we are temporarily becoming the connection user.
1620 if (!become_user(conn, conn->vuid)) {
1621 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1626 * make the directories version and version\driver_name
1627 * under the architecture directory.
1629 DEBUG(5,("Creating first directory\n"));
1630 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1631 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1632 mkdir_internal(conn, new_dir, bad_path);
1634 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1635 * listed for this driver which has already been moved, skip it (note:
1636 * drivers may list the same file name several times. Then check if the
1637 * file already exists in archi\cversion\, if so, check that the version
1638 * info (or time stamps if version info is unavailable) is newer (or the
1639 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1640 * Otherwise, delete the file.
1642 * If a file is not moved to archi\cversion\ because of an error, all the
1643 * rest of the 'unmoved' driver files are removed from archi\. If one or
1644 * more of the driver's files was already moved to archi\cversion\, it
1645 * potentially leaves the driver in a partially updated state. Version
1646 * trauma will most likely occur if an client attempts to use any printer
1647 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1648 * done is appropriate... later JRR
1651 DEBUG(5,("Moving files now !\n"));
1653 if (driver->driverpath && strlen(driver->driverpath)) {
1654 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1655 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1656 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1658 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1659 status = rename_internals(conn, new_name, old_name, 0, True);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1662 new_name, old_name));
1663 *perr = ntstatus_to_werror(status);
1664 unlink_internals(conn, 0, new_name);
1668 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1669 unlink_internals(conn, 0, new_name);
1673 if (driver->datafile && strlen(driver->datafile)) {
1674 if (!strequal(driver->datafile, driver->driverpath)) {
1675 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1676 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1677 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1679 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1680 status = rename_internals(conn, new_name, old_name, 0, True);
1681 if (!NT_STATUS_IS_OK(status)) {
1682 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1683 new_name, old_name));
1684 *perr = ntstatus_to_werror(status);
1685 unlink_internals(conn, 0, new_name);
1689 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1690 unlink_internals(conn, 0, new_name);
1695 if (driver->configfile && strlen(driver->configfile)) {
1696 if (!strequal(driver->configfile, driver->driverpath) &&
1697 !strequal(driver->configfile, driver->datafile)) {
1698 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1699 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1700 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1702 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1703 status = rename_internals(conn, new_name, old_name, 0, True);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1706 new_name, old_name));
1707 *perr = ntstatus_to_werror(status);
1708 unlink_internals(conn, 0, new_name);
1712 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1713 unlink_internals(conn, 0, new_name);
1718 if (driver->helpfile && strlen(driver->helpfile)) {
1719 if (!strequal(driver->helpfile, driver->driverpath) &&
1720 !strequal(driver->helpfile, driver->datafile) &&
1721 !strequal(driver->helpfile, driver->configfile)) {
1722 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1723 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1724 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1726 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1727 status = rename_internals(conn, new_name, old_name, 0, True);
1728 if (!NT_STATUS_IS_OK(status)) {
1729 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1730 new_name, old_name));
1731 *perr = ntstatus_to_werror(status);
1732 unlink_internals(conn, 0, new_name);
1736 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1737 unlink_internals(conn, 0, new_name);
1742 if (driver->dependentfiles) {
1743 for (i=0; *driver->dependentfiles[i]; i++) {
1744 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1745 !strequal(driver->dependentfiles[i], driver->datafile) &&
1746 !strequal(driver->dependentfiles[i], driver->configfile) &&
1747 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1749 for (j=0; j < i; j++) {
1750 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1755 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1756 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1757 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1759 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1760 status = rename_internals(conn, new_name, old_name, 0, True);
1761 if (!NT_STATUS_IS_OK(status)) {
1762 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1763 new_name, old_name));
1764 *perr = ntstatus_to_werror(status);
1765 unlink_internals(conn, 0, new_name);
1769 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1770 unlink_internals(conn, 0, new_name);
1777 close_cnum(conn, user->vuid);
1780 return ver == -1 ? False : True;
1783 /****************************************************************************
1784 ****************************************************************************/
1785 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1788 const char *architecture;
1794 TDB_DATA kbuf, dbuf;
1796 architecture = get_short_archi(driver->environment);
1798 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1799 * \\server is added in the rpc server layer.
1800 * It does make sense to NOT store the server's name in the printer TDB.
1803 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1805 /* .inf files do not always list a file for each of the four standard files.
1806 * Don't prepend a path to a null filename, or client claims:
1807 * "The server on which the printer resides does not have a suitable
1808 * <printer driver name> printer driver installed. Click OK if you
1809 * wish to install the driver on your local machine."
1811 if (strlen(driver->driverpath)) {
1812 fstrcpy(temp_name, driver->driverpath);
1813 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1816 if (strlen(driver->datafile)) {
1817 fstrcpy(temp_name, driver->datafile);
1818 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1821 if (strlen(driver->configfile)) {
1822 fstrcpy(temp_name, driver->configfile);
1823 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1826 if (strlen(driver->helpfile)) {
1827 fstrcpy(temp_name, driver->helpfile);
1828 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1831 if (driver->dependentfiles) {
1832 for (i=0; *driver->dependentfiles[i]; i++) {
1833 fstrcpy(temp_name, driver->dependentfiles[i]);
1834 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1838 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1840 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1847 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1850 driver->environment,
1855 driver->monitorname,
1856 driver->defaultdatatype);
1858 if (driver->dependentfiles) {
1859 for (i=0; *driver->dependentfiles[i]; i++) {
1860 len += tdb_pack(buf+len, buflen-len, "f",
1861 driver->dependentfiles[i]);
1865 if (len != buflen) {
1868 tb = (char *)SMB_REALLOC(buf, len);
1870 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1881 kbuf.dsize = strlen(key)+1;
1885 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1889 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1895 /****************************************************************************
1896 ****************************************************************************/
1897 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1899 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1902 info3.cversion = driver->version;
1903 fstrcpy(info3.name,driver->name);
1904 fstrcpy(info3.environment,driver->environment);
1905 fstrcpy(info3.driverpath,driver->driverpath);
1906 fstrcpy(info3.datafile,driver->datafile);
1907 fstrcpy(info3.configfile,driver->configfile);
1908 fstrcpy(info3.helpfile,driver->helpfile);
1909 fstrcpy(info3.monitorname,driver->monitorname);
1910 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1911 info3.dependentfiles = driver->dependentfiles;
1913 return add_a_printer_driver_3(&info3);
1917 /****************************************************************************
1918 ****************************************************************************/
1919 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1921 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1925 fstrcpy(info.name, driver);
1926 fstrcpy(info.defaultdatatype, "RAW");
1928 fstrcpy(info.driverpath, "");
1929 fstrcpy(info.datafile, "");
1930 fstrcpy(info.configfile, "");
1931 fstrcpy(info.helpfile, "");
1933 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
1936 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1937 fstrcpy(info.dependentfiles[0], "");
1939 *info_ptr = memdup(&info, sizeof(info));
1944 /****************************************************************************
1945 ****************************************************************************/
1946 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1948 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1949 TDB_DATA kbuf, dbuf;
1950 const char *architecture;
1955 ZERO_STRUCT(driver);
1957 architecture = get_short_archi(arch);
1959 if ( !architecture )
1960 return WERR_UNKNOWN_PRINTER_DRIVER;
1962 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1964 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1967 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1969 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1972 kbuf.dsize = strlen(key)+1;
1974 dbuf = tdb_fetch(tdb_drivers, kbuf);
1976 return WERR_UNKNOWN_PRINTER_DRIVER;
1978 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1987 driver.defaultdatatype);
1990 while (len < dbuf.dsize) {
1993 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
1994 if (tddfs == NULL) {
1995 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1998 else driver.dependentfiles = tddfs;
2000 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2001 &driver.dependentfiles[i]);
2005 if (driver.dependentfiles != NULL)
2006 fstrcpy(driver.dependentfiles[i], "");
2008 SAFE_FREE(dbuf.dptr);
2010 if (len != dbuf.dsize) {
2011 SAFE_FREE(driver.dependentfiles);
2013 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2016 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2021 /****************************************************************************
2022 Debugging function, dump at level 6 the struct in the logs.
2023 ****************************************************************************/
2025 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2028 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2031 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2037 if (driver.info_3 == NULL)
2040 info3=driver.info_3;
2042 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2043 DEBUGADD(20,("name:[%s]\n", info3->name));
2044 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2045 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2046 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2047 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2048 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2049 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2050 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2052 for (i=0; info3->dependentfiles &&
2053 *info3->dependentfiles[i]; i++) {
2054 DEBUGADD(20,("dependentfile:[%s]\n",
2055 info3->dependentfiles[i]));
2062 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2070 /****************************************************************************
2071 ****************************************************************************/
2072 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2076 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2081 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2082 nt_devmode->devicename,
2083 nt_devmode->formname,
2085 nt_devmode->specversion,
2086 nt_devmode->driverversion,
2088 nt_devmode->driverextra,
2089 nt_devmode->orientation,
2090 nt_devmode->papersize,
2091 nt_devmode->paperlength,
2092 nt_devmode->paperwidth,
2095 nt_devmode->defaultsource,
2096 nt_devmode->printquality,
2099 nt_devmode->yresolution,
2100 nt_devmode->ttoption,
2101 nt_devmode->collate,
2102 nt_devmode->logpixels,
2105 nt_devmode->bitsperpel,
2106 nt_devmode->pelswidth,
2107 nt_devmode->pelsheight,
2108 nt_devmode->displayflags,
2109 nt_devmode->displayfrequency,
2110 nt_devmode->icmmethod,
2111 nt_devmode->icmintent,
2112 nt_devmode->mediatype,
2113 nt_devmode->dithertype,
2114 nt_devmode->reserved1,
2115 nt_devmode->reserved2,
2116 nt_devmode->panningwidth,
2117 nt_devmode->panningheight,
2118 nt_devmode->private);
2121 if (nt_devmode->private) {
2122 len += tdb_pack(buf+len, buflen-len, "B",
2123 nt_devmode->driverextra,
2124 nt_devmode->private);
2127 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2132 /****************************************************************************
2133 Pack all values in all printer keys
2134 ***************************************************************************/
2136 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2140 REGISTRY_VALUE *val;
2141 REGVAL_CTR *val_ctr;
2148 /* loop over all keys */
2150 for ( i=0; i<data->num_keys; i++ ) {
2151 val_ctr = &data->keys[i].values;
2152 num_values = regval_ctr_numvals( val_ctr );
2154 /* loop over all values */
2156 for ( j=0; j<num_values; j++ ) {
2157 /* pathname should be stored as <key>\<value> */
2159 val = regval_ctr_specific_value( val_ctr, j );
2160 pstrcpy( path, data->keys[i].name );
2161 pstrcat( path, "\\" );
2162 pstrcat( path, regval_name(val) );
2164 len += tdb_pack(buf+len, buflen-len, "pPdB",
2169 regval_data_p(val) );
2176 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2182 /****************************************************************************
2183 Delete a printer - this just deletes the printer info file, any open
2184 handles are not affected.
2185 ****************************************************************************/
2187 uint32 del_a_printer(const char *sharename)
2191 pstring printdb_path;
2193 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2195 kbuf.dsize=strlen(key)+1;
2196 tdb_delete(tdb_printers, kbuf);
2198 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2200 kbuf.dsize=strlen(key)+1;
2201 tdb_delete(tdb_printers, kbuf);
2203 close_all_print_db();
2205 if (geteuid() == 0) {
2206 pstrcpy(printdb_path, lock_path("printing/"));
2207 pstrcat(printdb_path, sharename);
2208 pstrcat(printdb_path, ".tdb");
2210 unlink(printdb_path);
2216 /****************************************************************************
2217 ****************************************************************************/
2218 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2224 TDB_DATA kbuf, dbuf;
2227 * in addprinter: no servername and the printer is the name
2228 * in setprinter: servername is \\server
2229 * and printer is \\server\\printer
2231 * Samba manages only local printers.
2232 * we currently don't support things like i
2233 * path=\\other_server\printer
2235 * We only store the printername, not \\server\printername
2238 if ( info->servername[0] != '\0' ) {
2239 trim_string(info->printername, info->servername, NULL);
2240 trim_char(info->printername, '\\', '\0');
2241 info->servername[0]='\0';
2245 * JFM: one day I'll forget.
2246 * below that's info->portname because that's the SAMBA sharename
2247 * and I made NT 'thinks' it's the portname
2248 * the info->sharename is the thing you can name when you add a printer
2249 * that's the short-name when you create shared printer for 95/98
2250 * So I've made a limitation in SAMBA: you can only have 1 printer model
2251 * behind a SAMBA share.
2259 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2262 info->default_priority,
2279 info->printprocessor,
2283 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2285 len += pack_values( &info->data, buf+len, buflen-len );
2287 if (buflen != len) {
2290 tb = (char *)SMB_REALLOC(buf, len);
2292 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2302 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2305 kbuf.dsize = strlen(key)+1;
2309 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2312 if (!W_ERROR_IS_OK(ret))
2313 DEBUG(8, ("error updating printer to tdb on disk\n"));
2317 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2318 info->sharename, info->drivername, info->portname, len));
2324 /****************************************************************************
2325 Malloc and return an NT devicemode.
2326 ****************************************************************************/
2328 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2331 char adevice[MAXDEVICENAME];
2332 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2334 if (nt_devmode == NULL) {
2335 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2339 ZERO_STRUCTP(nt_devmode);
2341 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2342 fstrcpy(nt_devmode->devicename, adevice);
2344 fstrcpy(nt_devmode->formname, "Letter");
2346 nt_devmode->specversion = 0x0401;
2347 nt_devmode->driverversion = 0x0400;
2348 nt_devmode->size = 0x00DC;
2349 nt_devmode->driverextra = 0x0000;
2350 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2351 DEFAULTSOURCE | COPIES | SCALE |
2352 PAPERSIZE | ORIENTATION;
2353 nt_devmode->orientation = 1;
2354 nt_devmode->papersize = PAPER_LETTER;
2355 nt_devmode->paperlength = 0;
2356 nt_devmode->paperwidth = 0;
2357 nt_devmode->scale = 0x64;
2358 nt_devmode->copies = 1;
2359 nt_devmode->defaultsource = BIN_FORMSOURCE;
2360 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2361 nt_devmode->color = COLOR_MONOCHROME;
2362 nt_devmode->duplex = DUP_SIMPLEX;
2363 nt_devmode->yresolution = 0;
2364 nt_devmode->ttoption = TT_SUBDEV;
2365 nt_devmode->collate = COLLATE_FALSE;
2366 nt_devmode->icmmethod = 0;
2367 nt_devmode->icmintent = 0;
2368 nt_devmode->mediatype = 0;
2369 nt_devmode->dithertype = 0;
2371 /* non utilisés par un driver d'imprimante */
2372 nt_devmode->logpixels = 0;
2373 nt_devmode->bitsperpel = 0;
2374 nt_devmode->pelswidth = 0;
2375 nt_devmode->pelsheight = 0;
2376 nt_devmode->displayflags = 0;
2377 nt_devmode->displayfrequency = 0;
2378 nt_devmode->reserved1 = 0;
2379 nt_devmode->reserved2 = 0;
2380 nt_devmode->panningwidth = 0;
2381 nt_devmode->panningheight = 0;
2383 nt_devmode->private = NULL;
2387 /****************************************************************************
2388 Deepcopy an NT devicemode.
2389 ****************************************************************************/
2391 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2393 NT_DEVICEMODE *new_nt_devicemode = NULL;
2395 if ( !nt_devicemode )
2398 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2399 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2403 new_nt_devicemode->private = NULL;
2404 if (nt_devicemode->private != NULL) {
2405 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2406 SAFE_FREE(new_nt_devicemode);
2407 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2412 return new_nt_devicemode;
2415 /****************************************************************************
2416 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2417 ****************************************************************************/
2419 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2421 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2423 if(nt_devmode == NULL)
2426 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2428 SAFE_FREE(nt_devmode->private);
2429 SAFE_FREE(*devmode_ptr);
2432 /****************************************************************************
2433 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2434 ****************************************************************************/
2435 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2437 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2438 NT_PRINTER_DATA *data;
2444 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2446 free_nt_devicemode(&info->devmode);
2448 /* clean up all registry keys */
2451 for ( i=0; i<data->num_keys; i++ ) {
2452 SAFE_FREE( data->keys[i].name );
2453 regval_ctr_destroy( &data->keys[i].values );
2455 SAFE_FREE( data->keys );
2457 /* finally the top level structure */
2459 SAFE_FREE( *info_ptr );
2463 /****************************************************************************
2464 ****************************************************************************/
2465 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2469 NT_DEVICEMODE devmode;
2471 ZERO_STRUCT(devmode);
2473 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2475 if (!*nt_devmode) return len;
2477 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2481 &devmode.specversion,
2482 &devmode.driverversion,
2484 &devmode.driverextra,
2485 &devmode.orientation,
2487 &devmode.paperlength,
2488 &devmode.paperwidth,
2491 &devmode.defaultsource,
2492 &devmode.printquality,
2495 &devmode.yresolution,
2501 &devmode.bitsperpel,
2503 &devmode.pelsheight,
2504 &devmode.displayflags,
2505 &devmode.displayfrequency,
2509 &devmode.dithertype,
2512 &devmode.panningwidth,
2513 &devmode.panningheight,
2516 if (devmode.private) {
2517 /* the len in tdb_unpack is an int value and
2518 * devmode.driverextra is only a short
2520 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2521 devmode.driverextra=(uint16)extra_len;
2523 /* check to catch an invalid TDB entry so we don't segfault */
2524 if (devmode.driverextra == 0) {
2525 devmode.private = NULL;
2529 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2531 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2532 if (devmode.private)
2533 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2538 /****************************************************************************
2539 Allocate and initialize a new slot.
2540 ***************************************************************************/
2542 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2547 if ( !data || !name )
2550 /* allocate another slot in the NT_PRINTER_KEY array */
2552 d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1);
2556 key_index = data->num_keys;
2558 /* initialze new key */
2561 data->keys[key_index].name = SMB_STRDUP( name );
2563 ZERO_STRUCTP( &data->keys[key_index].values );
2565 regval_ctr_init( &data->keys[key_index].values );
2567 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2572 /****************************************************************************
2573 search for a registry key name in the existing printer data
2574 ***************************************************************************/
2576 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2581 if ( !data || !name )
2584 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2586 /* loop over all existing keys */
2588 for ( i=0; i<data->num_keys; i++ ) {
2589 if ( strequal(data->keys[i].name, name) ) {
2590 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2600 /****************************************************************************
2601 ***************************************************************************/
2603 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2607 int num_subkeys = 0;
2609 fstring *ptr, *subkeys_ptr = NULL;
2615 for ( i=0; i<data->num_keys; i++ ) {
2616 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2617 /* match sure it is a subkey and not the key itself */
2619 key_len = strlen( key );
2620 if ( strlen(data->keys[i].name) == key_len )
2623 /* get subkey path */
2625 p = data->keys[i].name + key_len;
2628 fstrcpy( subkeyname, p );
2629 if ( (p = strchr( subkeyname, '\\' )) )
2632 /* don't add a key more than once */
2634 for ( j=0; j<num_subkeys; j++ ) {
2635 if ( strequal( subkeys_ptr[j], subkeyname ) )
2639 if ( j != num_subkeys )
2642 /* found a match, so allocate space and copy the name */
2644 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2645 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2647 SAFE_FREE( subkeys );
2652 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2658 /* tag of the end */
2661 fstrcpy(subkeys_ptr[num_subkeys], "" );
2663 *subkeys = subkeys_ptr;
2669 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2672 smb_ucs2_t conv_str[1024];
2675 regval_ctr_delvalue(ctr, val_name);
2676 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2677 STR_TERMINATE | STR_NOALIGN);
2678 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2679 (char *) conv_str, str_size);
2682 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2685 regval_ctr_delvalue(ctr, val_name);
2686 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2687 (char *) &dword, sizeof(dword));
2690 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2693 uint8 bin_bool = (b ? 1 : 0);
2694 regval_ctr_delvalue(ctr, val_name);
2695 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2696 (char *) &bin_bool, sizeof(bin_bool));
2699 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2700 const char *multi_sz)
2702 smb_ucs2_t *conv_strs = NULL;
2705 /* a multi-sz has to have a null string terminator, i.e., the last
2706 string must be followed by two nulls */
2707 str_size = strlen(multi_sz) + 2;
2708 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2713 /* Change to byte units. */
2714 str_size *= sizeof(smb_ucs2_t);
2715 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2716 STR_TERMINATE | STR_NOALIGN);
2718 regval_ctr_delvalue(ctr, val_name);
2719 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2720 (char *) conv_strs, str_size);
2721 safe_free(conv_strs);
2725 /****************************************************************************
2726 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2728 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2729 * @return BOOL indicating success or failure
2730 ***************************************************************************/
2732 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2734 REGVAL_CTR *ctr = NULL;
2737 char *allocated_string = NULL;
2738 const char *ascii_str;
2741 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2742 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2743 ctr = &info2->data.keys[i].values;
2745 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2746 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2748 /* we make the assumption that the netbios name is the same
2749 as the DNS name sinc ethe former will be what we used to
2752 if ( get_mydnsdomname( dnssuffix ) )
2753 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2755 fstrcpy( longname, global_myname() );
2757 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2759 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2760 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2761 SAFE_FREE(allocated_string);
2763 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2764 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2765 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2766 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2767 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2768 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2769 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2770 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2771 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2773 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2774 (info2->attributes &
2775 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2777 switch (info2->attributes & 0x3) {
2779 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2782 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2785 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2788 ascii_str = "unknown";
2790 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2795 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2799 REGVAL_CTR *ctr=NULL;
2801 /* find the DsSpooler key */
2802 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2803 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2804 ctr = &info2->data.keys[i].values;
2806 regval_ctr_delvalue(ctr, "objectGUID");
2807 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2808 (char *) &guid, sizeof(struct uuid));
2811 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2812 NT_PRINTER_INFO_LEVEL *printer)
2816 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2817 char *srv_dn_utf8, **srv_cn_utf8;
2820 const char *attrs[] = {"objectGUID", NULL};
2822 WERROR win_rc = WERR_OK;
2824 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2826 /* figure out where to publish */
2827 ads_find_machine_acct(ads, &res, global_myname());
2829 /* We use ldap_get_dn here as we need the answer
2830 * in utf8 to call ldap_explode_dn(). JRA. */
2832 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2835 return WERR_SERVER_UNAVAILABLE;
2837 ads_msgfree(ads, res);
2838 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2840 ldap_memfree(srv_dn_utf8);
2842 return WERR_SERVER_UNAVAILABLE;
2844 /* Now convert to CH_UNIX. */
2845 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2846 ldap_memfree(srv_dn_utf8);
2847 ldap_memfree(srv_cn_utf8);
2849 return WERR_SERVER_UNAVAILABLE;
2851 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2852 ldap_memfree(srv_dn_utf8);
2853 ldap_memfree(srv_cn_utf8);
2856 return WERR_SERVER_UNAVAILABLE;
2859 ldap_memfree(srv_dn_utf8);
2860 ldap_memfree(srv_cn_utf8);
2862 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2863 printer->info_2->sharename, srv_dn);
2866 SAFE_FREE(srv_cn_0);
2868 /* build the ads mods */
2869 ctx = talloc_init("nt_printer_publish_ads");
2870 mods = ads_init_mods(ctx);
2872 get_local_printer_publishing_data(ctx, &mods,
2873 &printer->info_2->data);
2874 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2875 printer->info_2->sharename);
2878 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2879 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2880 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2882 if (!ADS_ERR_OK(ads_rc))
2883 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2885 talloc_destroy(ctx);
2887 /* retreive the guid and store it locally */
2888 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2890 ads_pull_guid(ads, res, &guid);
2891 ads_msgfree(ads, res);
2892 store_printer_guid(printer->info_2, guid);
2893 win_rc = mod_a_printer(printer, 2);
2900 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2901 NT_PRINTER_INFO_LEVEL *printer)
2905 char *prt_dn = NULL;
2907 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2909 /* remove the printer from the directory */
2910 ads_rc = ads_find_printer_on_server(ads, &res,
2911 printer->info_2->sharename, global_myname());
2913 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2914 prt_dn = ads_get_dn(ads, res);
2915 ads_rc = ads_del_dn(ads, prt_dn);
2916 ads_memfree(ads, prt_dn);
2919 ads_msgfree(ads, res);
2923 /****************************************************************************
2924 * Publish a printer in the directory
2926 * @param snum describing printer service
2927 * @return WERROR indicating status of publishing
2928 ***************************************************************************/
2930 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2933 ADS_STRUCT *ads = NULL;
2934 NT_PRINTER_INFO_LEVEL *printer = NULL;
2937 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2938 if (!W_ERROR_IS_OK(win_rc))
2942 case SPOOL_DS_PUBLISH:
2943 case SPOOL_DS_UPDATE:
2944 /* set the DsSpooler info and attributes */
2945 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2946 win_rc = WERR_NOMEM;
2950 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2952 case SPOOL_DS_UNPUBLISH:
2953 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2956 win_rc = WERR_NOT_SUPPORTED;
2960 win_rc = mod_a_printer(printer, 2);
2961 if (!W_ERROR_IS_OK(win_rc)) {
2962 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2966 ads = ads_init(NULL, NULL, NULL);
2968 DEBUG(3, ("ads_init() failed\n"));
2969 win_rc = WERR_SERVER_UNAVAILABLE;
2972 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2973 SAFE_FREE(ads->auth.password);
2974 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2977 /* ads_connect() will find the DC for us */
2978 ads_rc = ads_connect(ads);
2979 if (!ADS_ERR_OK(ads_rc)) {
2980 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2981 win_rc = WERR_ACCESS_DENIED;
2986 case SPOOL_DS_PUBLISH:
2987 case SPOOL_DS_UPDATE:
2988 win_rc = nt_printer_publish_ads(ads, printer);
2990 case SPOOL_DS_UNPUBLISH:
2991 win_rc = nt_printer_unpublish_ads(ads, printer);
2996 free_a_printer(&printer, 2);
3001 WERROR check_published_printers(void)
3004 ADS_STRUCT *ads = NULL;
3006 int n_services = lp_numservices();
3007 NT_PRINTER_INFO_LEVEL *printer = NULL;
3009 ads = ads_init(NULL, NULL, NULL);
3011 DEBUG(3, ("ads_init() failed\n"));
3012 return WERR_SERVER_UNAVAILABLE;
3014 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3015 SAFE_FREE(ads->auth.password);
3016 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3019 /* ads_connect() will find the DC for us */
3020 ads_rc = ads_connect(ads);
3021 if (!ADS_ERR_OK(ads_rc)) {
3022 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3024 return WERR_ACCESS_DENIED;
3027 for (snum = 0; snum < n_services; snum++) {
3028 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3031 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3032 lp_servicename(snum))) &&
3033 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3034 nt_printer_publish_ads(ads, printer);
3036 free_a_printer(&printer, 2);
3043 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3046 NT_PRINTER_INFO_LEVEL *printer = NULL;
3048 REGISTRY_VALUE *guid_val;
3052 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3054 if (!W_ERROR_IS_OK(win_rc) ||
3055 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3056 ((i = lookup_printerkey(&printer->info_2->data,
3057 SPOOL_DSSPOOLER_KEY)) < 0) ||
3058 !(ctr = &printer->info_2->data.keys[i].values) ||
3059 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3060 free_a_printer(&printer, 2);
3064 /* fetching printer guids really ought to be a separate function.. */
3065 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3066 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3068 free_a_printer(&printer, 2);
3072 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3077 WERROR check_published_printers(void)
3082 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3087 #endif /* HAVE_ADS */
3089 /****************************************************************************
3090 ***************************************************************************/
3092 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3094 NT_PRINTER_DATA *data;
3096 int removed_keys = 0;
3100 empty_slot = data->num_keys;
3103 return WERR_INVALID_PARAM;
3105 /* remove all keys */
3107 if ( !strlen(key) ) {
3108 for ( i=0; i<data->num_keys; i++ ) {
3109 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3110 data->keys[i].name));
3112 SAFE_FREE( data->keys[i].name );
3113 regval_ctr_destroy( &data->keys[i].values );
3116 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3119 SAFE_FREE( data->keys );
3120 ZERO_STRUCTP( data );
3125 /* remove a specific key (and all subkeys) */
3127 for ( i=0; i<data->num_keys; i++ ) {
3128 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3129 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3130 data->keys[i].name));
3132 SAFE_FREE( data->keys[i].name );
3133 regval_ctr_destroy( &data->keys[i].values );
3135 /* mark the slot as empty */
3137 ZERO_STRUCTP( &data->keys[i] );
3141 /* find the first empty slot */
3143 for ( i=0; i<data->num_keys; i++ ) {
3144 if ( !data->keys[i].name ) {
3151 if ( i == data->num_keys )
3152 /* nothing was removed */
3153 return WERR_INVALID_PARAM;
3155 /* move everything down */
3157 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3158 if ( data->keys[i].name ) {
3159 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3160 ZERO_STRUCTP( &data->keys[i] );
3168 data->num_keys -= removed_keys;
3170 /* sanity check to see if anything is left */
3172 if ( !data->num_keys ) {
3173 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3175 SAFE_FREE( data->keys );
3176 ZERO_STRUCTP( data );
3182 /****************************************************************************
3183 ***************************************************************************/
3185 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3187 WERROR result = WERR_OK;
3190 /* we must have names on non-zero length */
3192 if ( !key || !*key|| !value || !*value )
3193 return WERR_INVALID_NAME;
3195 /* find the printer key first */
3197 key_index = lookup_printerkey( &p2->data, key );
3198 if ( key_index == -1 )
3201 /* make sure the value exists so we can return the correct error code */
3203 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3204 return WERR_BADFILE;
3206 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3208 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3214 /****************************************************************************
3215 ***************************************************************************/
3217 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3218 uint32 type, uint8 *data, int real_len )
3220 WERROR result = WERR_OK;
3223 /* we must have names on non-zero length */
3225 if ( !key || !*key|| !value || !*value )
3226 return WERR_INVALID_NAME;
3228 /* find the printer key first */
3230 key_index = lookup_printerkey( &p2->data, key );
3231 if ( key_index == -1 )
3232 key_index = add_new_printer_key( &p2->data, key );
3234 if ( key_index == -1 )
3237 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3238 type, (const char *)data, real_len );
3240 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3241 key, value, type, real_len ));
3246 /****************************************************************************
3247 ***************************************************************************/
3249 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3253 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3256 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3259 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3262 /****************************************************************************
3263 Unpack a list of registry values frem the TDB
3264 ***************************************************************************/
3266 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3270 pstring string, valuename, keyname;
3274 REGISTRY_VALUE *regval_p;
3277 /* add the "PrinterDriverData" key first for performance reasons */
3279 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3281 /* loop and unpack the rest of the registry values */
3285 /* check to see if there are any more registry values */
3288 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3292 /* unpack the next regval */
3294 len += tdb_unpack(buf+len, buflen-len, "fdB",
3301 * break of the keyname from the value name.
3302 * Valuenames can have embedded '\'s so be careful.
3303 * only support one level of keys. See the
3304 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3308 str = strchr_m( string, '\\');
3310 /* Put in "PrinterDriverData" is no key specified */
3313 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3314 pstrcpy( valuename, string );
3318 pstrcpy( keyname, string );
3319 pstrcpy( valuename, str+1 );
3322 /* see if we need a new key */
3324 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3325 key_index = add_new_printer_key( printer_data, keyname );
3327 if ( key_index == -1 ) {
3328 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3333 /* add the new value */
3335 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3337 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3339 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3345 /****************************************************************************
3346 ***************************************************************************/
3348 static void map_to_os2_driver(fstring drivername)
3350 static BOOL initialised=False;
3351 static fstring last_from,last_to;
3352 char *mapfile = lp_os2_driver_map();
3353 char **lines = NULL;
3357 if (!strlen(drivername))
3364 *last_from = *last_to = 0;
3368 if (strequal(drivername,last_from)) {
3369 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3370 fstrcpy(drivername,last_to);
3374 lines = file_lines_load(mapfile, &numlines);
3375 if (numlines == 0) {
3376 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3380 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3382 for( i = 0; i < numlines; i++) {
3383 char *nt_name = lines[i];
3384 char *os2_name = strchr(nt_name,'=');
3391 while (isspace(*nt_name))
3394 if (!*nt_name || strchr("#;",*nt_name))
3398 int l = strlen(nt_name);
3399 while (l && isspace(nt_name[l-1])) {
3405 while (isspace(*os2_name))
3409 int l = strlen(os2_name);
3410 while (l && isspace(os2_name[l-1])) {
3416 if (strequal(nt_name,drivername)) {
3417 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3418 fstrcpy(last_from,drivername);
3419 fstrcpy(last_to,os2_name);
3420 fstrcpy(drivername,os2_name);
3421 file_lines_free(lines);
3426 file_lines_free(lines);
3429 /****************************************************************************
3430 Get a default printer info 2 struct.
3431 ****************************************************************************/
3432 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3435 NT_PRINTER_INFO_LEVEL_2 info;
3439 snum = lp_servicenumber(sharename);
3441 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3442 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3443 servername, sharename);
3444 fstrcpy(info.sharename, sharename);
3445 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3447 /* by setting the driver name to an empty string, a local NT admin
3448 can now run the **local** APW to install a local printer driver
3449 for a Samba shared printer in 2.2. Without this, drivers **must** be
3450 installed on the Samba server for NT clients --jerry */
3451 #if 0 /* JERRY --do not uncomment-- */
3452 if (!*info.drivername)
3453 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3457 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3459 pstrcpy(info.comment, "");
3460 fstrcpy(info.printprocessor, "winprint");
3461 fstrcpy(info.datatype, "RAW");
3463 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3465 info.starttime = 0; /* Minutes since 12:00am GMT */
3466 info.untiltime = 0; /* Minutes since 12:00am GMT */
3468 info.default_priority = 1;
3469 info.setuptime = (uint32)time(NULL);
3472 * I changed this as I think it is better to have a generic
3473 * DEVMODE than to crash Win2k explorer.exe --jerry
3474 * See the HP Deskjet 990c Win2k drivers for an example.
3476 * However the default devmode appears to cause problems
3477 * with the HP CLJ 8500 PCL driver. Hence the addition of
3478 * the "default devmode" parameter --jerry 22/01/2002
3481 if (lp_default_devmode(snum)) {
3482 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3486 info.devmode = NULL;
3489 /* This will get the current RPC talloc context, but we should be
3490 passing this as a parameter... fixme... JRA ! */
3492 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3495 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3497 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3505 free_nt_devicemode(&info.devmode);
3506 return WERR_ACCESS_DENIED;
3509 /****************************************************************************
3510 ****************************************************************************/
3511 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3514 NT_PRINTER_INFO_LEVEL_2 info;
3516 int snum = lp_servicenumber(sharename);
3517 TDB_DATA kbuf, dbuf;
3518 fstring printername;
3519 char adevice[MAXDEVICENAME];
3523 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3526 kbuf.dsize = strlen(key)+1;
3528 dbuf = tdb_fetch(tdb_printers, kbuf);
3530 return get_a_printer_2_default(info_ptr, servername, sharename);
3532 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3535 &info.default_priority,
3552 info.printprocessor,
3556 /* Samba has to have shared raw drivers. */
3557 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3558 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3560 /* Restore the stripped strings. */
3561 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3563 if ( lp_force_printername(snum) )
3564 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3566 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3568 fstrcpy(info.printername, printername);
3570 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3573 * Some client drivers freak out if there is a NULL devmode
3574 * (probably the driver is not checking before accessing
3575 * the devmode pointer) --jerry
3577 * See comments in get_a_printer_2_default()
3580 if (lp_default_devmode(snum) && !info.devmode) {
3581 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3583 info.devmode = construct_nt_devicemode(printername);
3586 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3588 fstrcpy(info.devmode->devicename, adevice);
3591 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3593 /* This will get the current RPC talloc context, but we should be
3594 passing this as a parameter... fixme... JRA ! */
3596 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3598 /* Fix for OS/2 drivers. */
3600 if (get_remote_arch() == RA_OS2)
3601 map_to_os2_driver(info.drivername);
3603 SAFE_FREE(dbuf.dptr);
3604 *info_ptr=memdup(&info, sizeof(info));
3606 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3607 sharename, info.printername, info.drivername));
3612 /****************************************************************************
3613 Debugging function, dump at level 6 the struct in the logs.
3614 ****************************************************************************/
3615 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3618 NT_PRINTER_INFO_LEVEL_2 *info2;
3620 DEBUG(106,("Dumping printer at level [%d]\n", level));
3625 if (printer->info_2 == NULL)
3629 info2=printer->info_2;
3631 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3632 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3633 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3634 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3635 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3636 DEBUGADD(106,("status:[%d]\n", info2->status));
3637 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3638 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3639 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3640 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3641 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3643 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3644 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3645 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3646 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3647 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3648 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3649 DEBUGADD(106,("location:[%s]\n", info2->location));
3650 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3651 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3652 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3653 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3659 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3667 /****************************************************************************
3668 Update the changeid time.
3669 This is SO NASTY as some drivers need this to change, others need it
3670 static. This value will change every second, and I must hope that this
3671 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3673 ****************************************************************************/
3675 static uint32 rev_changeid(void)
3679 get_process_uptime(&tv);
3682 /* Return changeid as msec since spooler restart */
3683 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3686 * This setting seems to work well but is too untested
3687 * to replace the above calculation. Left in for experiementation
3688 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3690 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3694 /********************************************************************
3695 Send a message to all smbds about the printer that just changed
3696 ********************************************************************/
3698 static BOOL send_printer_mod_msg( char* printername )
3700 int len = strlen(printername);
3705 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3708 /* spam everyone that we just changed this printer */
3710 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3716 * The function below are the high level ones.
3717 * only those ones must be called from the spoolss code.
3721 /****************************************************************************
3722 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3723 ****************************************************************************/
3725 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3729 dump_a_printer(printer, level);
3732 * invalidate cache for all open handles to this printer.
3733 * cache for a given handle will be updated on the next
3737 invalidate_printer_hnd_cache( printer->info_2->sharename );
3738 send_printer_mod_msg( printer->info_2->sharename );
3744 * Update the changestamp. Emperical tests show that the
3745 * ChangeID is always updated,but c_setprinter is
3746 * global spooler variable (not per printer).
3749 /* ChangeID **must** be increasing over the lifetime
3750 of client's spoolss service in order for the
3751 client's cache to show updates */
3753 printer->info_2->changeid = rev_changeid();
3756 * Because one day someone will ask:
3757 * NT->NT An admin connection to a remote
3758 * printer show changes imeediately in
3759 * the properities dialog
3761 * A non-admin connection will only show the
3762 * changes after viewing the properites page
3763 * 2 times. Seems to be related to a
3764 * race condition in the client between the spooler
3765 * updating the local cache and the Explorer.exe GUI
3766 * actually displaying the properties.
3768 * This is fixed in Win2k. admin/non-admin
3769 * connections both display changes immediately.
3774 result=update_a_printer_2(printer->info_2);
3779 result=WERR_UNKNOWN_LEVEL;
3786 /****************************************************************************
3787 Initialize printer devmode & data with previously saved driver init values.
3788 ****************************************************************************/
3790 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3794 TDB_DATA kbuf, dbuf;
3795 NT_PRINTER_INFO_LEVEL_2 info;
3801 * Delete any printer data 'values' already set. When called for driver
3802 * replace, there will generally be some, but during an add printer, there
3803 * should not be any (if there are delete them).
3806 delete_all_printer_data( info_ptr, "" );
3808 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3811 kbuf.dsize = strlen(key)+1;
3813 dbuf = tdb_fetch(tdb_drivers, kbuf);
3816 * When changing to a driver that has no init info in the tdb, remove
3817 * the previous drivers init info and leave the new on blank.
3819 free_nt_devicemode(&info_ptr->devmode);
3824 * Get the saved DEVMODE..
3827 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3830 * The saved DEVMODE contains the devicename from the printer used during
3831 * the initialization save. Change it to reflect the new printer.
3834 if ( info.devmode ) {
3835 ZERO_STRUCT(info.devmode->devicename);
3836 fstrcpy(info.devmode->devicename, info_ptr->printername);
3840 * NT/2k does not change out the entire DeviceMode of a printer
3841 * when changing the driver. Only the driverextra, private, &
3842 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3844 * Later examination revealed that Windows NT/2k does reset the
3845 * the printer's device mode, bit **only** when you change a
3846 * property of the device mode such as the page orientation.
3851 /* Bind the saved DEVMODE to the new the printer */
3853 free_nt_devicemode(&info_ptr->devmode);
3854 info_ptr->devmode = info.devmode;
3856 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3857 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3859 /* Add the printer data 'values' to the new printer */
3861 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3864 SAFE_FREE(dbuf.dptr);
3869 /****************************************************************************
3870 Initialize printer devmode & data with previously saved driver init values.
3871 When a printer is created using AddPrinter, the drivername bound to the
3872 printer is used to lookup previously saved driver initialization info, which
3873 is bound to the new printer.
3874 ****************************************************************************/
3876 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3878 BOOL result = False;
3882 result = set_driver_init_2(printer->info_2);
3886 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3894 /****************************************************************************
3895 Delete driver init data stored for a specified driver
3896 ****************************************************************************/
3898 BOOL del_driver_init(char *drivername)
3903 if (!drivername || !*drivername) {
3904 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3908 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3911 kbuf.dsize = strlen(key)+1;
3913 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3915 return (tdb_delete(tdb_drivers, kbuf) == 0);
3918 /****************************************************************************
3919 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3920 in the tdb. Note: this is different from the driver entry and the printer
3921 entry. There should be a single driver init entry for each driver regardless
3922 of whether it was installed from NT or 2K. Technically, they should be
3923 different, but they work out to the same struct.
3924 ****************************************************************************/
3926 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3930 int buflen, len, ret;
3931 TDB_DATA kbuf, dbuf;
3938 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3940 len += pack_values( &info->data, buf+len, buflen-len );
3945 tb = (char *)SMB_REALLOC(buf, len);
3947 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3957 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3960 kbuf.dsize = strlen(key)+1;
3964 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3968 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3972 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3973 info->sharename, info->drivername));
3978 /****************************************************************************
3979 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3980 ****************************************************************************/
3982 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3986 dump_a_printer(printer, level);
3990 result = update_driver_init_2(printer->info_2);
4000 /****************************************************************************
4001 Convert the printer data value, a REG_BINARY array, into an initialization
4002 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4003 got to keep the endians happy :).
4004 ****************************************************************************/
4006 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4008 BOOL result = False;
4012 ZERO_STRUCT(devmode);
4014 prs_init(&ps, 0, ctx, UNMARSHALL);
4015 ps.data_p = (char *)data;
4016 ps.buffer_size = data_len;
4018 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4019 result = convert_devicemode("", &devmode, &nt_devmode);
4021 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4026 /****************************************************************************
4027 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4029 1. Use the driver's config DLL to this UNC printername and:
4030 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4031 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4032 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4034 The last step triggers saving the "driver initialization" information for
4035 this printer into the tdb. Later, new printers that use this driver will
4036 have this initialization information bound to them. This simulates the
4037 driver initialization, as if it had run on the Samba server (as it would
4040 The Win32 client side code requirement sucks! But until we can run arbitrary
4041 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4043 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4044 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4045 about it and you will realize why. JRR 010720
4046 ****************************************************************************/
4048 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4050 WERROR status = WERR_OK;
4051 TALLOC_CTX *ctx = NULL;
4052 NT_DEVICEMODE *nt_devmode = NULL;
4053 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4056 * When the DEVMODE is already set on the printer, don't try to unpack it.
4058 DEBUG(8,("save_driver_init_2: Enter...\n"));
4060 if ( !printer->info_2->devmode && data_len ) {
4062 * Set devmode on printer info, so entire printer initialization can be
4066 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4069 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4070 status = WERR_NOMEM;
4074 ZERO_STRUCTP(nt_devmode);
4077 * The DEVMODE is held in the 'data' component of the param in raw binary.
4078 * Convert it to to a devmode structure
4080 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4081 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4082 status = WERR_INVALID_PARAM;
4086 printer->info_2->devmode = nt_devmode;
4090 * Pack up and add (or update) the DEVMODE and any current printer data to
4091 * a 'driver init' element in the tdb
4095 if ( update_driver_init(printer, 2) != 0 ) {
4096 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4097 status = WERR_NOMEM;
4102 * If driver initialization info was successfully saved, set the current
4103 * printer to match it. This allows initialization of the current printer
4104 * as well as the driver.
4106 status = mod_a_printer(printer, 2);
4107 if (!W_ERROR_IS_OK(status)) {
4108 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4109 printer->info_2->printername));
4113 talloc_destroy(ctx);
4114 free_nt_devicemode( &nt_devmode );
4116 printer->info_2->devmode = tmp_devmode;
4121 /****************************************************************************
4122 Update the driver init info (DEVMODE and specifics) for a printer
4123 ****************************************************************************/
4125 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4127 WERROR status = WERR_OK;
4131 status = save_driver_init_2( printer, data, data_len );
4134 status = WERR_UNKNOWN_LEVEL;
4141 /****************************************************************************
4142 Deep copy a NT_PRINTER_DATA
4143 ****************************************************************************/
4145 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4147 int i, j, num_vals, new_key_index;
4148 REGVAL_CTR *src_key, *dst_key;
4151 return NT_STATUS_NO_MEMORY;
4153 for ( i=0; i<src->num_keys; i++ ) {
4155 /* create a new instance of the printerkey in the destination
4156 printer_data object */
4158 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4159 dst_key = &dst->keys[new_key_index].values;
4161 src_key = &src->keys[i].values;
4162 num_vals = regval_ctr_numvals( src_key );
4164 /* dup the printer entire printer key */
4166 for ( j=0; j<num_vals; j++ ) {
4167 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4171 return NT_STATUS_OK;
4174 /****************************************************************************
4175 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4177 ****************************************************************************/
4179 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4181 NT_PRINTER_INFO_LEVEL_2 *copy;
4186 if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4189 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4191 /* malloc()'d members copied here */
4193 copy->devmode = dup_nt_devicemode( printer->devmode );
4195 ZERO_STRUCT( copy->data );
4196 copy_printer_data( ©->data, &printer->data );
4198 /* this is talloc()'d; very ugly that we have a structure that
4199 is half malloc()'d and half talloc()'d but that is the way
4200 that the PRINTER_INFO stuff is written right now. --jerry */
4202 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4207 /****************************************************************************
4208 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4210 Previously the code had a memory allocation problem because it always
4211 used the TALLOC_CTX from the Printer_entry*. This context lasts
4212 as a long as the original handle is open. So if the client made a lot
4213 of getprinter[data]() calls, the memory usage would climb. Now we use
4214 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4215 still use the Printer_entry->ctx for maintaining the cache copy though
4216 since that object must live as long as the handle by definition.
4219 ****************************************************************************/
4221 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4222 const char *sharename)
4225 NT_PRINTER_INFO_LEVEL *printer = NULL;
4230 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4234 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4235 DEBUG(0,("get_a_printer: malloc fail.\n"));
4238 ZERO_STRUCTP(printer);
4241 fstrcpy( servername, print_hnd->servername );
4243 fstrcpy( servername, "%L" );
4244 standard_sub_basic( "", servername, sizeof(servername)-1 );
4248 * check for cache first. A Printer handle cannot changed
4249 * to another printer object so we only check that the printer
4250 * is actually for a printer and that the printer_info pointer
4254 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4255 && print_hnd->printer_info )
4257 /* get_talloc_ctx() works here because we need a short
4258 lived talloc context */
4260 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4262 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4268 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4270 *pp_printer = printer;
4276 /* no cache for this handle; see if we can match one from another handle.
4277 Make sure to use a short lived talloc ctx */
4280 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4282 /* fail to disk if we don't have it with any open handle */
4284 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4285 result = get_a_printer_2(&printer->info_2, servername, sharename );
4287 /* we have a new printer now. Save it with this handle */
4289 if ( W_ERROR_IS_OK(result) ) {
4290 dump_a_printer(printer, level);
4292 /* save a copy in cache */
4293 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4294 if ( !print_hnd->printer_info )
4295 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4297 if ( print_hnd->printer_info ) {
4298 /* make sure to use the handle's talloc ctx here since
4299 the printer_2 object must last until the handle is closed */
4301 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4303 /* don't fail the lookup just because the cache update failed */
4304 if ( !print_hnd->printer_info->info_2 )
4305 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4308 *pp_printer = printer;
4316 result=WERR_UNKNOWN_LEVEL;
4320 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4325 /****************************************************************************
4326 Deletes a NT_PRINTER_INFO_LEVEL struct.
4327 ****************************************************************************/
4329 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4332 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4334 DEBUG(104,("freeing a printer at level [%d]\n", level));
4336 if (printer == NULL)
4341 if (printer->info_2 != NULL) {
4342 free_nt_printer_info_level_2(&printer->info_2);
4353 SAFE_FREE(*pp_printer);
4357 /****************************************************************************
4358 ****************************************************************************/
4359 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4362 DEBUG(104,("adding a printer at level [%d]\n", level));
4363 dump_a_printer_driver(driver, level);
4367 result=add_a_printer_driver_3(driver.info_3);
4371 result=add_a_printer_driver_6(driver.info_6);
4381 /****************************************************************************
4382 ****************************************************************************/
4384 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4385 fstring drivername, const char *architecture, uint32 version)
4391 /* Sometime we just want any version of the driver */
4393 if ( version == DRIVER_ANY_VERSION ) {
4394 /* look for Win2k first and then for NT4 */
4395 result = get_a_printer_driver_3(&driver->info_3, drivername,
4398 if ( !W_ERROR_IS_OK(result) ) {
4399 result = get_a_printer_driver_3( &driver->info_3,
4400 drivername, architecture, 2 );
4403 result = get_a_printer_driver_3(&driver->info_3, drivername,
4404 architecture, version);
4413 if (W_ERROR_IS_OK(result))
4414 dump_a_printer_driver(*driver, level);
4419 /****************************************************************************
4420 ****************************************************************************/
4421 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4428 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4429 if (driver.info_3 != NULL)
4431 info3=driver.info_3;
4432 SAFE_FREE(info3->dependentfiles);
4433 ZERO_STRUCTP(info3);
4443 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4444 if (driver.info_6 != NULL) {
4445 info6=driver.info_6;
4446 SAFE_FREE(info6->dependentfiles);
4447 SAFE_FREE(info6->previousnames);
4448 ZERO_STRUCTP(info6);
4464 /****************************************************************************
4465 Determine whether or not a particular driver is currently assigned
4467 ****************************************************************************/
4469 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4472 int n_services = lp_numservices();
4473 NT_PRINTER_INFO_LEVEL *printer = NULL;
4474 BOOL in_use = False;
4479 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4481 /* loop through the printers.tdb and check for the drivername */
4483 for (snum=0; snum<n_services && !in_use; snum++) {
4484 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4487 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4490 if ( strequal(info_3->name, printer->info_2->drivername) )
4493 free_a_printer( &printer, 2 );
4496 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4499 NT_PRINTER_DRIVER_INFO_LEVEL d;
4502 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4504 /* we can still remove the driver if there is one of
4505 "Windows NT x86" version 2 or 3 left */
4507 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4508 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4511 switch ( info_3->cversion ) {
4513 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4516 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4519 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4521 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4526 /* now check the error code */
4528 if ( W_ERROR_IS_OK(werr) ) {
4529 /* it's ok to remove the driver, we have other architctures left */
4531 free_a_printer_driver( d, 3 );
4535 /* report that the driver is not in use by default */
4541 /**********************************************************************
4542 Check to see if a ogiven file is in use by *info
4543 *********************************************************************/
4545 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4552 if ( strequal(file, info->driverpath) )
4555 if ( strequal(file, info->datafile) )
4558 if ( strequal(file, info->configfile) )
4561 if ( strequal(file, info->helpfile) )
4564 /* see of there are any dependent files to examine */
4566 if ( !info->dependentfiles )
4569 while ( *info->dependentfiles[i] ) {
4570 if ( strequal(file, info->dependentfiles[i]) )
4579 /**********************************************************************
4580 Utility function to remove the dependent file pointed to by the
4581 input parameter from the list
4582 *********************************************************************/
4584 static void trim_dependent_file( fstring files[], int idx )
4587 /* bump everything down a slot */
4589 while( *files[idx+1] ) {
4590 fstrcpy( files[idx], files[idx+1] );
4599 /**********************************************************************
4600 Check if any of the files used by src are also used by drv
4601 *********************************************************************/
4603 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4604 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4606 BOOL in_use = False;
4612 /* check each file. Remove it from the src structure if it overlaps */
4614 if ( drv_file_in_use(src->driverpath, drv) ) {
4616 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4617 fstrcpy( src->driverpath, "" );
4620 if ( drv_file_in_use(src->datafile, drv) ) {
4622 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4623 fstrcpy( src->datafile, "" );
4626 if ( drv_file_in_use(src->configfile, drv) ) {
4628 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4629 fstrcpy( src->configfile, "" );
4632 if ( drv_file_in_use(src->helpfile, drv) ) {
4634 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4635 fstrcpy( src->helpfile, "" );
4638 /* are there any dependentfiles to examine? */
4640 if ( !src->dependentfiles )
4643 while ( *src->dependentfiles[i] ) {
4644 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4646 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4647 trim_dependent_file( src->dependentfiles, i );
4655 /****************************************************************************
4656 Determine whether or not a particular driver files are currently being
4657 used by any other driver.
4659 Return value is True if any files were in use by other drivers
4660 and False otherwise.
4662 Upon return, *info has been modified to only contain the driver files
4663 which are not in use
4664 ****************************************************************************/
4666 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4671 fstring *list = NULL;
4672 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4677 version = info->cversion;
4679 /* loop over all driver versions */
4681 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4683 /* get the list of drivers */
4686 ndrivers = get_ntdrivers(&list, info->environment, version);
4688 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4689 ndrivers, info->environment, version));
4691 /* check each driver for overlap in files */
4693 for (i=0; i<ndrivers; i++) {
4694 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4696 ZERO_STRUCT(driver);
4698 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4703 /* check if d2 uses any files from d1 */
4704 /* only if this is a different driver than the one being deleted */
4706 if ( !strequal(info->name, driver.info_3->name) ) {
4707 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4708 free_a_printer_driver(driver, 3);
4714 free_a_printer_driver(driver, 3);
4719 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4721 driver.info_3 = info;
4723 if ( DEBUGLEVEL >= 20 )
4724 dump_a_printer_driver( driver, 3 );
4729 /****************************************************************************
4730 Actually delete the driver files. Make sure that
4731 printer_driver_files_in_use() return False before calling
4733 ****************************************************************************/
4735 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4739 connection_struct *conn;
4749 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4752 * Connect to the print$ share under the same account as the
4753 * user connected to the rpc pipe. Note we must be root to
4757 null_pw = data_blob( NULL, 0 );
4758 fstrcpy(res_type, "A:");
4760 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4764 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4768 /* Save who we are - we are temporarily becoming the connection user. */
4770 if ( !become_user(conn, conn->vuid) ) {
4771 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4775 /* now delete the files; must strip the '\print$' string from
4778 if ( *info_3->driverpath ) {
4779 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4780 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4781 DEBUG(10,("deleting driverfile [%s]\n", s));
4782 unlink_internals(conn, 0, s);
4786 if ( *info_3->configfile ) {
4787 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4788 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4789 DEBUG(10,("deleting configfile [%s]\n", s));
4790 unlink_internals(conn, 0, s);
4794 if ( *info_3->datafile ) {
4795 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4796 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4797 DEBUG(10,("deleting datafile [%s]\n", s));
4798 unlink_internals(conn, 0, s);
4802 if ( *info_3->helpfile ) {
4803 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4804 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4805 DEBUG(10,("deleting helpfile [%s]\n", s));
4806 unlink_internals(conn, 0, s);
4810 /* check if we are done removing files */
4812 if ( info_3->dependentfiles ) {
4813 while ( *info_3->dependentfiles[i] ) {
4816 /* bypass the "\print$" portion of the path */
4818 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4819 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4820 DEBUG(10,("deleting dependent file [%s]\n", file));
4821 unlink_internals(conn, 0, file );
4833 /****************************************************************************
4834 Remove a printer driver from the TDB. This assumes that the the driver was
4835 previously looked up.
4836 ***************************************************************************/
4838 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4839 uint32 version, BOOL delete_files )
4843 TDB_DATA kbuf, dbuf;
4844 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4846 /* delete the tdb data first */
4848 arch = get_short_archi(info_3->environment);
4849 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4850 arch, version, info_3->name);
4852 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4853 key, delete_files ? "TRUE" : "FALSE" ));
4855 ctr.info_3 = info_3;
4856 dump_a_printer_driver( ctr, 3 );
4859 kbuf.dsize=strlen(key)+1;
4861 /* check if the driver actually exists for this environment */
4863 dbuf = tdb_fetch( tdb_drivers, kbuf );
4865 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4866 return WERR_UNKNOWN_PRINTER_DRIVER;
4869 SAFE_FREE( dbuf.dptr );
4871 /* ok... the driver exists so the delete should return success */
4873 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4874 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4875 return WERR_ACCESS_DENIED;
4879 * now delete any associated files if delete_files == True
4880 * even if this part failes, we return succes because the
4881 * driver doesn not exist any more
4885 delete_driver_files( info_3, user );
4888 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4893 /****************************************************************************
4894 Store a security desc for a printer.
4895 ****************************************************************************/
4897 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4899 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4900 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4902 TALLOC_CTX *mem_ctx = NULL;
4906 mem_ctx = talloc_init("nt_printing_setsec");
4907 if (mem_ctx == NULL)
4910 /* The old owner and group sids of the security descriptor are not
4911 present when new ACEs are added or removed by changing printer
4912 permissions through NT. If they are NULL in the new security
4913 descriptor then copy them over from the old one. */
4915 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4916 DOM_SID *owner_sid, *group_sid;
4917 SEC_ACL *dacl, *sacl;
4918 SEC_DESC *psd = NULL;
4921 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4923 /* Pick out correct owner and group sids */
4925 owner_sid = secdesc_ctr->sec->owner_sid ?
4926 secdesc_ctr->sec->owner_sid :
4927 old_secdesc_ctr->sec->owner_sid;
4929 group_sid = secdesc_ctr->sec->grp_sid ?
4930 secdesc_ctr->sec->grp_sid :
4931 old_secdesc_ctr->sec->grp_sid;
4933 dacl = secdesc_ctr->sec->dacl ?
4934 secdesc_ctr->sec->dacl :
4935 old_secdesc_ctr->sec->dacl;
4937 sacl = secdesc_ctr->sec->sacl ?
4938 secdesc_ctr->sec->sacl :
4939 old_secdesc_ctr->sec->sacl;
4941 /* Make a deep copy of the security descriptor */
4943 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4944 owner_sid, group_sid,
4949 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4952 if (!new_secdesc_ctr) {
4953 new_secdesc_ctr = secdesc_ctr;
4956 /* Store the security descriptor in a tdb */
4958 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4959 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4961 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4963 status = WERR_BADFUNC;
4967 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4969 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4972 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4973 status = WERR_BADFUNC;
4976 /* Free malloc'ed memory */
4982 talloc_destroy(mem_ctx);
4986 /****************************************************************************
4987 Construct a default security descriptor buffer for a printer.
4988 ****************************************************************************/
4990 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4992 SEC_ACE ace[5]; /* max number of ace entries */
4995 SEC_ACL *psa = NULL;
4996 SEC_DESC_BUF *sdb = NULL;
4997 SEC_DESC *psd = NULL;
5001 /* Create an ACE where Everyone is allowed to print */
5003 init_sec_access(&sa, PRINTER_ACE_PRINT);
5004 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5005 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5007 /* Make the security descriptor owned by the Administrators group
5008 on the PDC of the domain. */
5010 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5011 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5014 /* Backup plan - make printer owned by admins.
5015 This should emulate a lanman printer as security
5016 settings can't be changed. */
5018 sid_copy(&owner_sid, get_global_sam_sid());
5019 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5022 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5023 init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5024 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
5025 SEC_ACE_FLAG_INHERIT_ONLY);
5027 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5028 init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5029 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5031 /* Add the domain admins group if we are a DC */
5034 DOM_SID domadmins_sid;
5036 sid_copy(&domadmins_sid, get_global_sam_sid());
5037 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5039 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5040 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5041 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
5042 SEC_ACE_FLAG_INHERIT_ONLY);
5044 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5045 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5046 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5049 /* The ACL revision number in rpc_secdesc.h differs from the one
5050 created by NT when setting ACE entries in printer
5051 descriptors. NT4 complains about the property being edited by a
5054 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5055 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5057 NULL, psa, &sd_size);
5061 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5065 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5067 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5068 (unsigned int)sd_size));
5073 /****************************************************************************
5074 Get a security desc for a printer.
5075 ****************************************************************************/
5077 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
5083 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
5084 printername = temp + 1;
5087 /* Fetch security descriptor from tdb */
5089 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
5091 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5092 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5094 DEBUG(4,("using default secdesc for %s\n", printername));
5096 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5100 /* Save default security descriptor for later */
5102 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5103 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5105 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5106 tdb_prs_store(tdb_printers, key, &ps);
5113 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5114 this security descriptor has been created when winbindd was
5115 down. Take ownership of security descriptor. */
5117 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5120 /* Change sd owner to workgroup administrator */
5122 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5123 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5124 SEC_DESC *psd = NULL;
5129 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5131 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5133 (*secdesc_ctr)->sec->grp_sid,
5134 (*secdesc_ctr)->sec->sacl,
5135 (*secdesc_ctr)->sec->dacl,
5138 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5140 /* Swap with other one */
5142 *secdesc_ctr = new_secdesc_ctr;
5146 nt_printing_setsec(printername, *secdesc_ctr);
5150 if (DEBUGLEVEL >= 10) {
5151 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5154 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5155 printername, the_acl->num_aces));
5157 for (i = 0; i < the_acl->num_aces; i++) {
5160 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5162 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5163 the_acl->ace[i].type, the_acl->ace[i].flags,
5164 the_acl->ace[i].info.mask));
5174 1: level not implemented
5175 2: file doesn't exist
5176 3: can't allocate memory
5177 4: can't free memory
5178 5: non existant struct
5182 A printer and a printer driver are 2 different things.
5183 NT manages them separatelly, Samba does the same.
5184 Why ? Simply because it's easier and it makes sense !
5186 Now explanation: You have 3 printers behind your samba server,
5187 2 of them are the same make and model (laser A and B). But laser B
5188 has an 3000 sheet feeder and laser A doesn't such an option.
5189 Your third printer is an old dot-matrix model for the accounting :-).
5191 If the /usr/local/samba/lib directory (default dir), you will have
5192 5 files to describe all of this.
5194 3 files for the printers (1 by printer):
5197 NTprinter_accounting
5198 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5199 NTdriver_printer model X
5200 NTdriver_printer model Y
5202 jfm: I should use this comment for the text file to explain
5203 same thing for the forms BTW.
5204 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5208 /* Convert generic access rights to printer object specific access rights.
5209 It turns out that NT4 security descriptors use generic access rights and
5210 NT5 the object specific ones. */
5212 void map_printer_permissions(SEC_DESC *sd)
5216 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5217 se_map_generic(&sd->dacl->ace[i].info.mask,
5218 &printer_generic_mapping);
5222 /****************************************************************************
5223 Check a user has permissions to perform the given operation. We use the
5224 permission constants defined in include/rpc_spoolss.h to check the various
5225 actions we perform when checking printer access.
5227 PRINTER_ACCESS_ADMINISTER:
5228 print_queue_pause, print_queue_resume, update_printer_sec,
5229 update_printer, spoolss_addprinterex_level_2,
5230 _spoolss_setprinterdata
5235 JOB_ACCESS_ADMINISTER:
5236 print_job_delete, print_job_pause, print_job_resume,
5239 Try access control in the following order (for performance reasons):
5240 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5241 2) check security descriptor (bit comparisons in memory)
5242 3) "printer admins" (may result in numerous calls to winbind)
5244 ****************************************************************************/
5245 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5247 SEC_DESC_BUF *secdesc = NULL;
5248 uint32 access_granted;
5252 TALLOC_CTX *mem_ctx = NULL;
5253 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5255 /* If user is NULL then use the current_user structure */
5258 user = ¤t_user;
5260 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5262 if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5266 /* Get printer name */
5268 pname = PRINTERNAME(snum);
5270 if (!pname || !*pname) {
5275 /* Get printer security descriptor */
5277 if(!(mem_ctx = talloc_init("print_access_check"))) {
5282 nt_printing_getsec(mem_ctx, pname, &secdesc);
5284 if (access_type == JOB_ACCESS_ADMINISTER) {
5285 SEC_DESC_BUF *parent_secdesc = secdesc;
5287 /* Create a child security descriptor to check permissions
5288 against. This is because print jobs are child objects
5289 objects of a printer. */
5291 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5293 /* Now this is the bit that really confuses me. The access
5294 type needs to be changed from JOB_ACCESS_ADMINISTER to
5295 PRINTER_ACCESS_ADMINISTER for this to work. Something
5296 to do with the child (job) object becoming like a
5299 access_type = PRINTER_ACCESS_ADMINISTER;
5304 map_printer_permissions(secdesc->sec);
5306 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5307 &access_granted, &status);
5309 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5311 /* see if we need to try the printer admin list */
5313 if ( access_granted == 0 ) {
5314 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5318 talloc_destroy(mem_ctx);
5326 /****************************************************************************
5327 Check the time parameters allow a print operation.
5328 *****************************************************************************/
5330 BOOL print_time_access_check(int snum)
5332 NT_PRINTER_INFO_LEVEL *printer = NULL;
5334 time_t now = time(NULL);
5338 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5341 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5345 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5347 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5350 free_a_printer(&printer, 2);
5358 /****************************************************************************
5359 Fill in the servername sent in the _spoolss_open_printer_ex() call
5360 ****************************************************************************/
5361 char* get_server_name( Printer_entry *printer )
5363 return printer->servername;