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, SEC_DESC_SELF_RELATIVE,
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( "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 const char *vstring = "INFO/version";
419 if ( tdb_drivers && tdb_printers && tdb_forms )
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 /* handle a Samba upgrade */
450 tdb_lock_bystring(tdb_drivers, vstring, 0);
452 /* ---------------- Start Lock Region ---------------- */
454 /* Cope with byte-reversed older versions of the db. */
455 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
457 if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
459 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
460 /* Written on a bigendian machine with old fetch_int code. Save as le. */
461 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
462 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
463 vers_id = NTDRIVERS_DATABASE_VERSION_3;
466 if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
468 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
469 if (!upgrade_to_version_3())
472 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
474 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
477 /* at this point we know that the database is at version 3 so upgrade to v4 */
479 if ( !upgrade_to_version_4() )
481 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
484 /* ---------------- End Lock Region ------------------ */
486 tdb_unlock_bystring(tdb_drivers, vstring);
488 update_c_setprinter(True);
491 * register callback to handle updating printers as new
492 * drivers are installed
495 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
498 * register callback to handle updating printer data
499 * when a driver is initialized
502 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
505 * register callback to handle invalidating the printer cache
506 * between smbd processes.
509 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
511 /* of course, none of the message callbacks matter if you don't
512 tell messages.c that you interested in receiving PRINT_GENERAL
513 msgs. This is done in claim_connection() */
516 if ( lp_security() == SEC_ADS ) {
517 win_rc = check_published_printers();
518 if (!W_ERROR_IS_OK(win_rc))
519 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
525 /*******************************************************************
526 Function to allow filename parsing "the old way".
527 ********************************************************************/
529 static BOOL driver_unix_convert(char *name,connection_struct *conn,
530 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
533 unix_clean_name(name);
534 trim_string(name,"/","/");
535 return unix_convert(name, conn, saved_last_component, bad_path, pst);
538 /*******************************************************************
539 tdb traversal function for counting printers.
540 ********************************************************************/
542 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
543 TDB_DATA data, void *context)
545 int *printer_count = (int*)context;
547 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
549 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
555 /*******************************************************************
556 Update the spooler global c_setprinter. This variable is initialized
557 when the parent smbd starts with the number of existing printers. It
558 is monotonically increased by the current number of printers *after*
559 each add or delete printer RPC. Only Microsoft knows why... JRR020119
560 ********************************************************************/
562 uint32 update_c_setprinter(BOOL initialize)
565 int32 printer_count = 0;
567 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
569 /* Traverse the tdb, counting the printers */
570 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
572 /* If initializing, set c_setprinter to current printers count
573 * otherwise, bump it by the current printer count
576 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
578 c_setprinter = printer_count;
580 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
581 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
583 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
585 return (uint32)c_setprinter;
588 /*******************************************************************
589 Get the spooler global c_setprinter, accounting for initialization.
590 ********************************************************************/
592 uint32 get_c_setprinter(void)
594 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
596 if (c_setprinter == (int32)-1)
597 c_setprinter = update_c_setprinter(True);
599 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
601 return (uint32)c_setprinter;
604 /****************************************************************************
605 Get builtin form struct list.
606 ****************************************************************************/
608 int get_builtin_ntforms(nt_forms_struct **list)
610 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
611 return sizeof(default_forms) / sizeof(default_forms[0]);
614 /****************************************************************************
615 get a builtin form struct
616 ****************************************************************************/
618 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
622 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
623 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
624 count = sizeof(default_forms) / sizeof(default_forms[0]);
625 for (i=0;i<count;i++) {
626 if (strequal(form_name,default_forms[i].name)) {
627 DEBUGADD(6,("Found builtin form %s \n", form_name));
628 memcpy(form,&default_forms[i],sizeof(*form));
636 /****************************************************************************
637 get a form struct list
638 ****************************************************************************/
639 int get_ntforms(nt_forms_struct **list)
641 TDB_DATA kbuf, newkey, dbuf;
643 nt_forms_struct form;
648 for (kbuf = tdb_firstkey(tdb_forms);
650 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
652 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
655 dbuf = tdb_fetch(tdb_forms, kbuf);
659 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
660 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
661 &i, &form.flag, &form.width, &form.length, &form.left,
662 &form.top, &form.right, &form.bottom);
663 SAFE_FREE(dbuf.dptr);
664 if (ret != dbuf.dsize)
667 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
669 DEBUG(0,("get_ntforms: Realloc fail.\n"));
681 /****************************************************************************
682 write a form struct list
683 ****************************************************************************/
684 int write_ntforms(nt_forms_struct **list, int number)
691 for (i=0;i<number;i++) {
692 /* save index, so list is rebuilt in correct order */
693 len = tdb_pack(buf, sizeof(buf), "dddddddd",
694 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
695 (*list)[i].left, (*list)[i].top, (*list)[i].right,
697 if (len > sizeof(buf)) break;
698 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
699 kbuf.dsize = strlen(key)+1;
703 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
709 /****************************************************************************
710 add a form struct at the end of the list
711 ****************************************************************************/
712 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
720 * NT tries to add forms even when
721 * they are already in the base
722 * only update the values if already present
727 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
728 for (n=0; n<*count; n++) {
729 if ( strequal((*list)[n].name, form_name) ) {
736 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
737 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
741 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
745 (*list)[n].flag=form->flags;
746 (*list)[n].width=form->size_x;
747 (*list)[n].length=form->size_y;
748 (*list)[n].left=form->left;
749 (*list)[n].top=form->top;
750 (*list)[n].right=form->right;
751 (*list)[n].bottom=form->bottom;
753 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
754 update ? "updated" : "added", form_name));
759 /****************************************************************************
760 Delete a named form struct.
761 ****************************************************************************/
763 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
772 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
774 for (n=0; n<*count; n++) {
775 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
776 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
782 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
783 *ret = WERR_INVALID_PARAM;
787 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
788 kbuf.dsize = strlen(key)+1;
790 if (tdb_delete(tdb_forms, kbuf) != 0) {
798 /****************************************************************************
799 Update a form struct.
800 ****************************************************************************/
802 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
806 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
808 DEBUG(106, ("[%s]\n", form_name));
809 for (n=0; n<count; n++) {
810 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
811 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
815 if (n==count) return;
817 (*list)[n].flag=form->flags;
818 (*list)[n].width=form->size_x;
819 (*list)[n].length=form->size_y;
820 (*list)[n].left=form->left;
821 (*list)[n].top=form->top;
822 (*list)[n].right=form->right;
823 (*list)[n].bottom=form->bottom;
826 /****************************************************************************
827 Get the nt drivers list.
828 Traverse the database and look-up the matching names.
829 ****************************************************************************/
830 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
833 const char *short_archi;
836 TDB_DATA kbuf, newkey;
838 short_archi = get_short_archi(architecture);
839 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
841 for (kbuf = tdb_firstkey(tdb_drivers);
843 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
845 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
848 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
849 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
854 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
861 /****************************************************************************
862 function to do the mapping between the long architecture name and
864 ****************************************************************************/
865 const char *get_short_archi(const char *long_archi)
869 DEBUG(107,("Getting architecture dependant directory\n"));
872 } while ( (archi_table[i].long_archi!=NULL ) &&
873 StrCaseCmp(long_archi, archi_table[i].long_archi) );
875 if (archi_table[i].long_archi==NULL) {
876 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
880 /* this might be client code - but shouldn't this be an fstrcpy etc? */
883 DEBUGADD(108,("index: [%d]\n", i));
884 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
885 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
887 return archi_table[i].short_archi;
890 /****************************************************************************
891 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
892 There are two case to be covered here: PE (Portable Executable) and NE (New
893 Executable) files. Both files support the same INFO structure, but PE files
894 store the signature in unicode, and NE files store it as !unicode.
895 returns -1 on error, 1 on version info found, and 0 on no version info found.
896 ****************************************************************************/
898 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
904 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
905 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
906 fname, PE_HEADER_SIZE));
910 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
911 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
912 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
913 fname, (unsigned long)byte_count));
914 goto no_version_info;
917 /* Is this really a DOS header? */
918 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
919 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
920 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
921 goto no_version_info;
924 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
925 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
926 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
928 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
929 goto no_version_info;
932 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
933 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
934 fname, (unsigned long)byte_count));
935 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
936 goto no_version_info;
939 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
940 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
941 unsigned int num_sections;
942 unsigned int section_table_bytes;
944 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
945 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
946 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
947 /* At this point, we assume the file is in error. It still could be somthing
948 * else besides a PE file, but it unlikely at this point.
953 /* get the section table */
954 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
955 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
956 if (section_table_bytes == 0)
960 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
961 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
962 fname, section_table_bytes));
966 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
967 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
968 fname, (unsigned long)byte_count));
972 /* Iterate the section table looking for the resource section ".rsrc" */
973 for (i = 0; i < num_sections; i++) {
974 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
976 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
977 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
978 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
980 if (section_bytes == 0)
984 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
985 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
986 fname, section_bytes));
990 /* Seek to the start of the .rsrc section info */
991 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
992 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
997 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
998 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
999 fname, (unsigned long)byte_count));
1003 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1006 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1007 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1008 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1009 /* Align to next long address */
1010 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1012 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1013 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1014 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1016 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1017 fname, *major, *minor,
1018 (*major>>16)&0xffff, *major&0xffff,
1019 (*minor>>16)&0xffff, *minor&0xffff));
1028 /* Version info not found, fall back to origin date/time */
1029 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1033 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1034 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1035 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1036 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1037 /* At this point, we assume the file is in error. It still could be somthing
1038 * else besides a NE file, but it unlikely at this point. */
1042 /* Allocate a bit more space to speed up things */
1044 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1045 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1046 fname, PE_HEADER_SIZE));
1050 /* This is a HACK! I got tired of trying to sort through the messy
1051 * 'NE' file format. If anyone wants to clean this up please have at
1052 * it, but this works. 'NE' files will eventually fade away. JRR */
1053 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1054 /* Cover case that should not occur in a well formed 'NE' .dll file */
1055 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1057 for(i=0; i<byte_count; i++) {
1058 /* Fast skip past data that can't possibly match */
1059 if (buf[i] != 'V') continue;
1061 /* Potential match data crosses buf boundry, move it to beginning
1062 * of buf, and fill the buf with as much as it will hold. */
1063 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1066 memcpy(buf, &buf[i], byte_count-i);
1067 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1068 (byte_count-i))) < 0) {
1070 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1075 byte_count = bc + (byte_count - i);
1076 if (byte_count<VS_VERSION_INFO_SIZE) break;
1081 /* Check that the full signature string and the magic number that
1082 * follows exist (not a perfect solution, but the chances that this
1083 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1084 * twice, as it is simpler to read the code. */
1085 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1086 /* Compute skip alignment to next long address */
1087 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1088 sizeof(VS_SIGNATURE)) & 3;
1089 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1091 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1092 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1093 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1094 fname, *major, *minor,
1095 (*major>>16)&0xffff, *major&0xffff,
1096 (*minor>>16)&0xffff, *minor&0xffff));
1103 /* Version info not found, fall back to origin date/time */
1104 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1109 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1110 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1111 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1122 /****************************************************************************
1123 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1124 share one or more files. During the MS installation process files are checked
1125 to insure that only a newer version of a shared file is installed over an
1126 older version. There are several possibilities for this comparison. If there
1127 is no previous version, the new one is newer (obviously). If either file is
1128 missing the version info structure, compare the creation date (on Unix use
1129 the modification date). Otherwise chose the numerically larger version number.
1130 ****************************************************************************/
1132 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1134 BOOL use_version = True;
1139 time_t new_create_time;
1143 time_t old_create_time;
1147 files_struct *fsp = NULL;
1149 SMB_STRUCT_STAT stat_buf;
1152 SET_STAT_INVALID(st);
1153 SET_STAT_INVALID(stat_buf);
1154 new_create_time = (time_t)0;
1155 old_create_time = (time_t)0;
1157 /* Get file version info (if available) for previous file (if it exists) */
1158 pstrcpy(filepath, old_file);
1160 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1162 fsp = open_file_shared(conn, filepath, &stat_buf,
1163 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1164 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1165 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1167 /* Old file not found, so by definition new file is in fact newer */
1168 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1173 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1174 if (ret == -1) goto error_exit;
1177 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1179 use_version = False;
1180 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1181 old_create_time = st.st_mtime;
1182 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1185 close_file(fsp, True);
1187 /* Get file version info (if available) for new file */
1188 pstrcpy(filepath, new_file);
1189 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1191 fsp = open_file_shared(conn, filepath, &stat_buf,
1192 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1193 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1194 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1196 /* New file not found, this shouldn't occur if the caller did its job */
1197 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1202 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1203 if (ret == -1) goto error_exit;
1206 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1208 use_version = False;
1209 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1210 new_create_time = st.st_mtime;
1211 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1214 close_file(fsp, True);
1216 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1217 /* Compare versions and choose the larger version number */
1218 if (new_major > old_major ||
1219 (new_major == old_major && new_minor > old_minor)) {
1221 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1225 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1230 /* Compare modification time/dates and choose the newest time/date */
1231 if (new_create_time > old_create_time) {
1232 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1236 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1243 close_file(fsp, True);
1247 /****************************************************************************
1248 Determine the correct cVersion associated with an architecture and driver
1249 ****************************************************************************/
1250 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1251 struct current_user *user, WERROR *perr)
1260 files_struct *fsp = NULL;
1263 connection_struct *conn;
1265 SET_STAT_INVALID(st);
1267 *perr = WERR_INVALID_PARAM;
1269 /* If architecture is Windows 95/98/ME, the version is always 0. */
1270 if (strcmp(architecture, "WIN40") == 0) {
1271 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1277 * Connect to the print$ share under the same account as the user connected
1278 * to the rpc pipe. Note we must still be root to do this.
1281 /* Null password is ok - we are already an authenticated user... */
1282 null_pw = data_blob(NULL, 0);
1283 fstrcpy(res_type, "A:");
1285 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1289 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1290 *perr = ntstatus_to_werror(nt_status);
1294 /* We are temporarily becoming the connection user. */
1295 if (!become_user(conn, user->vuid)) {
1296 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1297 *perr = WERR_ACCESS_DENIED;
1301 /* Open the driver file (Portable Executable format) and determine the
1302 * deriver the cversion. */
1303 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1305 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1307 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1308 *perr = WERR_BADFILE;
1312 fsp = open_file_shared(conn, driverpath, &st,
1313 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1314 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1315 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1318 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1319 driverpath, errno));
1320 *perr = WERR_ACCESS_DENIED;
1326 int ret = get_file_version(fsp, driverpath, &major, &minor);
1327 if (ret == -1) goto error_exit;
1330 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1335 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1336 * for more details. Version in this case is not just the version of the
1337 * file, but the version in the sense of kernal mode (2) vs. user mode
1338 * (3) drivers. Other bits of the version fields are the version info.
1341 cversion = major & 0x0000ffff;
1343 case 2: /* WinNT drivers */
1344 case 3: /* Win2K drivers */
1348 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1349 driverpath, cversion));
1353 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1354 driverpath, major, minor));
1357 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1358 driverpath, cversion));
1360 close_file(fsp, True);
1361 close_cnum(conn, user->vuid);
1370 close_file(fsp, True);
1372 close_cnum(conn, user->vuid);
1377 /****************************************************************************
1378 ****************************************************************************/
1379 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1380 struct current_user *user)
1382 const char *architecture;
1388 /* clean up the driver name.
1389 * we can get .\driver.dll
1390 * or worse c:\windows\system\driver.dll !
1392 /* using an intermediate string to not have overlaping memcpy()'s */
1393 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1394 fstrcpy(new_name, p+1);
1395 fstrcpy(driver->driverpath, new_name);
1398 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1399 fstrcpy(new_name, p+1);
1400 fstrcpy(driver->datafile, new_name);
1403 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1404 fstrcpy(new_name, p+1);
1405 fstrcpy(driver->configfile, new_name);
1408 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1409 fstrcpy(new_name, p+1);
1410 fstrcpy(driver->helpfile, new_name);
1413 if (driver->dependentfiles) {
1414 for (i=0; *driver->dependentfiles[i]; i++) {
1415 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1416 fstrcpy(new_name, p+1);
1417 fstrcpy(driver->dependentfiles[i], new_name);
1422 architecture = get_short_archi(driver->environment);
1424 /* jfm:7/16/2000 the client always sends the cversion=0.
1425 * The server should check which version the driver is by reading
1426 * the PE header of driver->driverpath.
1428 * For Windows 95/98 the version is 0 (so the value sent is correct)
1429 * For Windows NT (the architecture doesn't matter)
1430 * NT 3.1: cversion=0
1431 * NT 3.5/3.51: cversion=1
1435 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1441 /****************************************************************************
1442 ****************************************************************************/
1443 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1445 const char *architecture;
1451 /* clean up the driver name.
1452 * we can get .\driver.dll
1453 * or worse c:\windows\system\driver.dll !
1455 /* using an intermediate string to not have overlaping memcpy()'s */
1456 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1457 fstrcpy(new_name, p+1);
1458 fstrcpy(driver->driverpath, new_name);
1461 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1462 fstrcpy(new_name, p+1);
1463 fstrcpy(driver->datafile, new_name);
1466 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1467 fstrcpy(new_name, p+1);
1468 fstrcpy(driver->configfile, new_name);
1471 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1472 fstrcpy(new_name, p+1);
1473 fstrcpy(driver->helpfile, new_name);
1476 if (driver->dependentfiles) {
1477 for (i=0; *driver->dependentfiles[i]; i++) {
1478 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1479 fstrcpy(new_name, p+1);
1480 fstrcpy(driver->dependentfiles[i], new_name);
1485 architecture = get_short_archi(driver->environment);
1487 /* jfm:7/16/2000 the client always sends the cversion=0.
1488 * The server should check which version the driver is by reading
1489 * the PE header of driver->driverpath.
1491 * For Windows 95/98 the version is 0 (so the value sent is correct)
1492 * For Windows NT (the architecture doesn't matter)
1493 * NT 3.1: cversion=0
1494 * NT 3.5/3.51: cversion=1
1499 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1505 /****************************************************************************
1506 ****************************************************************************/
1507 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1508 uint32 level, struct current_user *user)
1513 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1514 driver=driver_abstract.info_3;
1515 return clean_up_driver_struct_level_3(driver, user);
1519 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1520 driver=driver_abstract.info_6;
1521 return clean_up_driver_struct_level_6(driver, user);
1524 return WERR_INVALID_PARAM;
1528 /****************************************************************************
1529 This function sucks and should be replaced. JRA.
1530 ****************************************************************************/
1532 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1534 dst->cversion = src->version;
1536 fstrcpy( dst->name, src->name);
1537 fstrcpy( dst->environment, src->environment);
1538 fstrcpy( dst->driverpath, src->driverpath);
1539 fstrcpy( dst->datafile, src->datafile);
1540 fstrcpy( dst->configfile, src->configfile);
1541 fstrcpy( dst->helpfile, src->helpfile);
1542 fstrcpy( dst->monitorname, src->monitorname);
1543 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1544 dst->dependentfiles = src->dependentfiles;
1547 #if 0 /* Debugging function */
1549 static char* ffmt(unsigned char *c){
1551 static char ffmt_str[17];
1553 for (i=0; i<16; i++) {
1554 if ((c[i] < ' ') || (c[i] > '~'))
1565 /****************************************************************************
1566 ****************************************************************************/
1567 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1568 struct current_user *user, WERROR *perr)
1570 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1571 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1572 const char *architecture;
1577 connection_struct *conn;
1588 memset(inbuf, '\0', sizeof(inbuf));
1589 memset(outbuf, '\0', sizeof(outbuf));
1593 driver=driver_abstract.info_3;
1594 else if (level==6) {
1595 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1596 driver = &converted_driver;
1598 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1599 return WERR_UNKNOWN_LEVEL;
1602 architecture = get_short_archi(driver->environment);
1605 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1606 * Note we must be root to do this.
1609 null_pw = data_blob(NULL, 0);
1610 fstrcpy(res_type, "A:");
1612 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1616 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1617 *perr = ntstatus_to_werror(nt_status);
1618 return WERR_NO_SUCH_SHARE;
1622 * Save who we are - we are temporarily becoming the connection user.
1625 if (!become_user(conn, conn->vuid)) {
1626 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1627 return WERR_ACCESS_DENIED;
1631 * make the directories version and version\driver_name
1632 * under the architecture directory.
1634 DEBUG(5,("Creating first directory\n"));
1635 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1636 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1637 mkdir_internal(conn, new_dir, bad_path);
1639 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1640 * listed for this driver which has already been moved, skip it (note:
1641 * drivers may list the same file name several times. Then check if the
1642 * file already exists in archi\cversion\, if so, check that the version
1643 * info (or time stamps if version info is unavailable) is newer (or the
1644 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1645 * Otherwise, delete the file.
1647 * If a file is not moved to archi\cversion\ because of an error, all the
1648 * rest of the 'unmoved' driver files are removed from archi\. If one or
1649 * more of the driver's files was already moved to archi\cversion\, it
1650 * potentially leaves the driver in a partially updated state. Version
1651 * trauma will most likely occur if an client attempts to use any printer
1652 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1653 * done is appropriate... later JRR
1656 DEBUG(5,("Moving files now !\n"));
1658 if (driver->driverpath && strlen(driver->driverpath)) {
1659 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1660 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1661 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1663 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1664 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1665 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1666 new_name, old_name));
1667 *perr = ntstatus_to_werror(status);
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 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1681 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1682 new_name, old_name));
1683 *perr = ntstatus_to_werror(status);
1690 if (driver->configfile && strlen(driver->configfile)) {
1691 if (!strequal(driver->configfile, driver->driverpath) &&
1692 !strequal(driver->configfile, driver->datafile)) {
1693 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1694 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1695 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1697 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1698 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1699 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1700 new_name, old_name));
1701 *perr = ntstatus_to_werror(status);
1708 if (driver->helpfile && strlen(driver->helpfile)) {
1709 if (!strequal(driver->helpfile, driver->driverpath) &&
1710 !strequal(driver->helpfile, driver->datafile) &&
1711 !strequal(driver->helpfile, driver->configfile)) {
1712 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1713 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1714 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1716 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1717 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1718 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1719 new_name, old_name));
1720 *perr = ntstatus_to_werror(status);
1727 if (driver->dependentfiles) {
1728 for (i=0; *driver->dependentfiles[i]; i++) {
1729 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1730 !strequal(driver->dependentfiles[i], driver->datafile) &&
1731 !strequal(driver->dependentfiles[i], driver->configfile) &&
1732 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1734 for (j=0; j < i; j++) {
1735 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1740 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1741 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1742 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1744 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1745 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1746 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1747 new_name, old_name));
1748 *perr = ntstatus_to_werror(status);
1757 close_cnum(conn, user->vuid);
1760 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1763 /****************************************************************************
1764 ****************************************************************************/
1765 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1768 const char *architecture;
1774 TDB_DATA kbuf, dbuf;
1776 architecture = get_short_archi(driver->environment);
1778 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1779 * \\server is added in the rpc server layer.
1780 * It does make sense to NOT store the server's name in the printer TDB.
1783 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1785 /* .inf files do not always list a file for each of the four standard files.
1786 * Don't prepend a path to a null filename, or client claims:
1787 * "The server on which the printer resides does not have a suitable
1788 * <printer driver name> printer driver installed. Click OK if you
1789 * wish to install the driver on your local machine."
1791 if (strlen(driver->driverpath)) {
1792 fstrcpy(temp_name, driver->driverpath);
1793 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1796 if (strlen(driver->datafile)) {
1797 fstrcpy(temp_name, driver->datafile);
1798 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1801 if (strlen(driver->configfile)) {
1802 fstrcpy(temp_name, driver->configfile);
1803 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1806 if (strlen(driver->helpfile)) {
1807 fstrcpy(temp_name, driver->helpfile);
1808 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1811 if (driver->dependentfiles) {
1812 for (i=0; *driver->dependentfiles[i]; i++) {
1813 fstrcpy(temp_name, driver->dependentfiles[i]);
1814 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1818 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1820 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1827 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1830 driver->environment,
1835 driver->monitorname,
1836 driver->defaultdatatype);
1838 if (driver->dependentfiles) {
1839 for (i=0; *driver->dependentfiles[i]; i++) {
1840 len += tdb_pack(buf+len, buflen-len, "f",
1841 driver->dependentfiles[i]);
1845 if (len != buflen) {
1848 tb = (char *)SMB_REALLOC(buf, len);
1850 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1861 kbuf.dsize = strlen(key)+1;
1865 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1869 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1875 /****************************************************************************
1876 ****************************************************************************/
1877 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1879 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1882 info3.cversion = driver->version;
1883 fstrcpy(info3.name,driver->name);
1884 fstrcpy(info3.environment,driver->environment);
1885 fstrcpy(info3.driverpath,driver->driverpath);
1886 fstrcpy(info3.datafile,driver->datafile);
1887 fstrcpy(info3.configfile,driver->configfile);
1888 fstrcpy(info3.helpfile,driver->helpfile);
1889 fstrcpy(info3.monitorname,driver->monitorname);
1890 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1891 info3.dependentfiles = driver->dependentfiles;
1893 return add_a_printer_driver_3(&info3);
1897 /****************************************************************************
1898 ****************************************************************************/
1899 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1901 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1905 fstrcpy(info.name, driver);
1906 fstrcpy(info.defaultdatatype, "RAW");
1908 fstrcpy(info.driverpath, "");
1909 fstrcpy(info.datafile, "");
1910 fstrcpy(info.configfile, "");
1911 fstrcpy(info.helpfile, "");
1913 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
1916 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1917 fstrcpy(info.dependentfiles[0], "");
1919 *info_ptr = memdup(&info, sizeof(info));
1924 /****************************************************************************
1925 ****************************************************************************/
1926 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1928 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1929 TDB_DATA kbuf, dbuf;
1930 const char *architecture;
1935 ZERO_STRUCT(driver);
1937 architecture = get_short_archi(arch);
1939 if ( !architecture )
1940 return WERR_UNKNOWN_PRINTER_DRIVER;
1942 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1944 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1947 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1949 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1952 kbuf.dsize = strlen(key)+1;
1954 dbuf = tdb_fetch(tdb_drivers, kbuf);
1956 return WERR_UNKNOWN_PRINTER_DRIVER;
1958 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1967 driver.defaultdatatype);
1970 while (len < dbuf.dsize) {
1973 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
1974 if (tddfs == NULL) {
1975 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1978 else driver.dependentfiles = tddfs;
1980 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1981 &driver.dependentfiles[i]);
1985 if (driver.dependentfiles != NULL)
1986 fstrcpy(driver.dependentfiles[i], "");
1988 SAFE_FREE(dbuf.dptr);
1990 if (len != dbuf.dsize) {
1991 SAFE_FREE(driver.dependentfiles);
1993 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1996 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2001 /****************************************************************************
2002 Debugging function, dump at level 6 the struct in the logs.
2003 ****************************************************************************/
2005 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2008 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2011 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2017 if (driver.info_3 == NULL)
2020 info3=driver.info_3;
2022 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2023 DEBUGADD(20,("name:[%s]\n", info3->name));
2024 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2025 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2026 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2027 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2028 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2029 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2030 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2032 for (i=0; info3->dependentfiles &&
2033 *info3->dependentfiles[i]; i++) {
2034 DEBUGADD(20,("dependentfile:[%s]\n",
2035 info3->dependentfiles[i]));
2042 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2050 /****************************************************************************
2051 ****************************************************************************/
2052 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2056 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2061 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2062 nt_devmode->devicename,
2063 nt_devmode->formname,
2065 nt_devmode->specversion,
2066 nt_devmode->driverversion,
2068 nt_devmode->driverextra,
2069 nt_devmode->orientation,
2070 nt_devmode->papersize,
2071 nt_devmode->paperlength,
2072 nt_devmode->paperwidth,
2075 nt_devmode->defaultsource,
2076 nt_devmode->printquality,
2079 nt_devmode->yresolution,
2080 nt_devmode->ttoption,
2081 nt_devmode->collate,
2082 nt_devmode->logpixels,
2085 nt_devmode->bitsperpel,
2086 nt_devmode->pelswidth,
2087 nt_devmode->pelsheight,
2088 nt_devmode->displayflags,
2089 nt_devmode->displayfrequency,
2090 nt_devmode->icmmethod,
2091 nt_devmode->icmintent,
2092 nt_devmode->mediatype,
2093 nt_devmode->dithertype,
2094 nt_devmode->reserved1,
2095 nt_devmode->reserved2,
2096 nt_devmode->panningwidth,
2097 nt_devmode->panningheight,
2098 nt_devmode->nt_dev_private);
2101 if (nt_devmode->nt_dev_private) {
2102 len += tdb_pack(buf+len, buflen-len, "B",
2103 nt_devmode->driverextra,
2104 nt_devmode->nt_dev_private);
2107 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2112 /****************************************************************************
2113 Pack all values in all printer keys
2114 ***************************************************************************/
2116 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2120 REGISTRY_VALUE *val;
2121 REGVAL_CTR *val_ctr;
2128 /* loop over all keys */
2130 for ( i=0; i<data->num_keys; i++ ) {
2131 val_ctr = &data->keys[i].values;
2132 num_values = regval_ctr_numvals( val_ctr );
2134 /* loop over all values */
2136 for ( j=0; j<num_values; j++ ) {
2137 /* pathname should be stored as <key>\<value> */
2139 val = regval_ctr_specific_value( val_ctr, j );
2140 pstrcpy( path, data->keys[i].name );
2141 pstrcat( path, "\\" );
2142 pstrcat( path, regval_name(val) );
2144 len += tdb_pack(buf+len, buflen-len, "pPdB",
2149 regval_data_p(val) );
2156 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2162 /****************************************************************************
2163 Delete a printer - this just deletes the printer info file, any open
2164 handles are not affected.
2165 ****************************************************************************/
2167 uint32 del_a_printer(const char *sharename)
2171 pstring printdb_path;
2173 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2175 kbuf.dsize=strlen(key)+1;
2176 tdb_delete(tdb_printers, kbuf);
2178 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2180 kbuf.dsize=strlen(key)+1;
2181 tdb_delete(tdb_printers, kbuf);
2183 close_all_print_db();
2185 if (geteuid() == 0) {
2186 pstrcpy(printdb_path, lock_path("printing/"));
2187 pstrcat(printdb_path, sharename);
2188 pstrcat(printdb_path, ".tdb");
2190 unlink(printdb_path);
2196 /****************************************************************************
2197 ****************************************************************************/
2198 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2204 TDB_DATA kbuf, dbuf;
2207 * in addprinter: no servername and the printer is the name
2208 * in setprinter: servername is \\server
2209 * and printer is \\server\\printer
2211 * Samba manages only local printers.
2212 * we currently don't support things like i
2213 * path=\\other_server\printer
2215 * We only store the printername, not \\server\printername
2218 if ( info->servername[0] != '\0' ) {
2219 trim_string(info->printername, info->servername, NULL);
2220 trim_char(info->printername, '\\', '\0');
2221 info->servername[0]='\0';
2225 * JFM: one day I'll forget.
2226 * below that's info->portname because that's the SAMBA sharename
2227 * and I made NT 'thinks' it's the portname
2228 * the info->sharename is the thing you can name when you add a printer
2229 * that's the short-name when you create shared printer for 95/98
2230 * So I've made a limitation in SAMBA: you can only have 1 printer model
2231 * behind a SAMBA share.
2239 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2242 info->default_priority,
2259 info->printprocessor,
2263 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2265 len += pack_values( &info->data, buf+len, buflen-len );
2267 if (buflen != len) {
2270 tb = (char *)SMB_REALLOC(buf, len);
2272 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2282 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2285 kbuf.dsize = strlen(key)+1;
2289 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2292 if (!W_ERROR_IS_OK(ret))
2293 DEBUG(8, ("error updating printer to tdb on disk\n"));
2297 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2298 info->sharename, info->drivername, info->portname, len));
2304 /****************************************************************************
2305 Malloc and return an NT devicemode.
2306 ****************************************************************************/
2308 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2311 char adevice[MAXDEVICENAME];
2312 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2314 if (nt_devmode == NULL) {
2315 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2319 ZERO_STRUCTP(nt_devmode);
2321 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2322 fstrcpy(nt_devmode->devicename, adevice);
2324 fstrcpy(nt_devmode->formname, "Letter");
2326 nt_devmode->specversion = 0x0401;
2327 nt_devmode->driverversion = 0x0400;
2328 nt_devmode->size = 0x00DC;
2329 nt_devmode->driverextra = 0x0000;
2330 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2331 DEFAULTSOURCE | COPIES | SCALE |
2332 PAPERSIZE | ORIENTATION;
2333 nt_devmode->orientation = 1;
2334 nt_devmode->papersize = PAPER_LETTER;
2335 nt_devmode->paperlength = 0;
2336 nt_devmode->paperwidth = 0;
2337 nt_devmode->scale = 0x64;
2338 nt_devmode->copies = 1;
2339 nt_devmode->defaultsource = BIN_FORMSOURCE;
2340 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2341 nt_devmode->color = COLOR_MONOCHROME;
2342 nt_devmode->duplex = DUP_SIMPLEX;
2343 nt_devmode->yresolution = 0;
2344 nt_devmode->ttoption = TT_SUBDEV;
2345 nt_devmode->collate = COLLATE_FALSE;
2346 nt_devmode->icmmethod = 0;
2347 nt_devmode->icmintent = 0;
2348 nt_devmode->mediatype = 0;
2349 nt_devmode->dithertype = 0;
2351 /* non utilisés par un driver d'imprimante */
2352 nt_devmode->logpixels = 0;
2353 nt_devmode->bitsperpel = 0;
2354 nt_devmode->pelswidth = 0;
2355 nt_devmode->pelsheight = 0;
2356 nt_devmode->displayflags = 0;
2357 nt_devmode->displayfrequency = 0;
2358 nt_devmode->reserved1 = 0;
2359 nt_devmode->reserved2 = 0;
2360 nt_devmode->panningwidth = 0;
2361 nt_devmode->panningheight = 0;
2363 nt_devmode->nt_dev_private = NULL;
2367 /****************************************************************************
2368 Deepcopy an NT devicemode.
2369 ****************************************************************************/
2371 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2373 NT_DEVICEMODE *new_nt_devicemode = NULL;
2375 if ( !nt_devicemode )
2378 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2379 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2383 new_nt_devicemode->nt_dev_private = NULL;
2384 if (nt_devicemode->nt_dev_private != NULL) {
2385 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2386 SAFE_FREE(new_nt_devicemode);
2387 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2392 return new_nt_devicemode;
2395 /****************************************************************************
2396 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2397 ****************************************************************************/
2399 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2401 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2403 if(nt_devmode == NULL)
2406 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2408 SAFE_FREE(nt_devmode->nt_dev_private);
2409 SAFE_FREE(*devmode_ptr);
2412 /****************************************************************************
2413 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2414 ****************************************************************************/
2415 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2417 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2418 NT_PRINTER_DATA *data;
2424 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2426 free_nt_devicemode(&info->devmode);
2428 /* clean up all registry keys */
2431 for ( i=0; i<data->num_keys; i++ ) {
2432 SAFE_FREE( data->keys[i].name );
2433 regval_ctr_destroy( &data->keys[i].values );
2435 SAFE_FREE( data->keys );
2437 /* finally the top level structure */
2439 SAFE_FREE( *info_ptr );
2443 /****************************************************************************
2444 ****************************************************************************/
2445 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2449 NT_DEVICEMODE devmode;
2451 ZERO_STRUCT(devmode);
2453 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2455 if (!*nt_devmode) return len;
2457 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2461 &devmode.specversion,
2462 &devmode.driverversion,
2464 &devmode.driverextra,
2465 &devmode.orientation,
2467 &devmode.paperlength,
2468 &devmode.paperwidth,
2471 &devmode.defaultsource,
2472 &devmode.printquality,
2475 &devmode.yresolution,
2481 &devmode.bitsperpel,
2483 &devmode.pelsheight,
2484 &devmode.displayflags,
2485 &devmode.displayfrequency,
2489 &devmode.dithertype,
2492 &devmode.panningwidth,
2493 &devmode.panningheight,
2494 &devmode.nt_dev_private);
2496 if (devmode.nt_dev_private) {
2497 /* the len in tdb_unpack is an int value and
2498 * devmode.driverextra is only a short
2500 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2501 devmode.driverextra=(uint16)extra_len;
2503 /* check to catch an invalid TDB entry so we don't segfault */
2504 if (devmode.driverextra == 0) {
2505 devmode.nt_dev_private = NULL;
2509 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2511 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2512 if (devmode.nt_dev_private)
2513 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2518 /****************************************************************************
2519 Allocate and initialize a new slot.
2520 ***************************************************************************/
2522 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2527 if ( !data || !name )
2530 /* allocate another slot in the NT_PRINTER_KEY array */
2532 d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1);
2536 key_index = data->num_keys;
2538 /* initialze new key */
2541 data->keys[key_index].name = SMB_STRDUP( name );
2543 regval_ctr_init( &data->keys[key_index].values );
2545 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2550 /****************************************************************************
2551 search for a registry key name in the existing printer data
2552 ***************************************************************************/
2554 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2559 if ( !data || !name )
2562 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2564 /* loop over all existing keys */
2566 for ( i=0; i<data->num_keys; i++ ) {
2567 if ( strequal(data->keys[i].name, name) ) {
2568 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2578 /****************************************************************************
2579 ***************************************************************************/
2581 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2585 int num_subkeys = 0;
2587 fstring *ptr, *subkeys_ptr = NULL;
2593 for ( i=0; i<data->num_keys; i++ ) {
2594 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2595 /* match sure it is a subkey and not the key itself */
2597 key_len = strlen( key );
2598 if ( strlen(data->keys[i].name) == key_len )
2601 /* get subkey path */
2603 p = data->keys[i].name + key_len;
2606 fstrcpy( subkeyname, p );
2607 if ( (p = strchr( subkeyname, '\\' )) )
2610 /* don't add a key more than once */
2612 for ( j=0; j<num_subkeys; j++ ) {
2613 if ( strequal( subkeys_ptr[j], subkeyname ) )
2617 if ( j != num_subkeys )
2620 /* found a match, so allocate space and copy the name */
2622 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2623 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2625 SAFE_FREE( subkeys );
2630 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2636 /* tag of the end */
2639 fstrcpy(subkeys_ptr[num_subkeys], "" );
2641 *subkeys = subkeys_ptr;
2647 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2650 smb_ucs2_t conv_str[1024];
2653 regval_ctr_delvalue(ctr, val_name);
2654 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2655 STR_TERMINATE | STR_NOALIGN);
2656 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2657 (char *) conv_str, str_size);
2660 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2663 regval_ctr_delvalue(ctr, val_name);
2664 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2665 (char *) &dword, sizeof(dword));
2668 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2671 uint8 bin_bool = (b ? 1 : 0);
2672 regval_ctr_delvalue(ctr, val_name);
2673 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2674 (char *) &bin_bool, sizeof(bin_bool));
2677 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2678 const char *multi_sz)
2680 smb_ucs2_t *conv_strs = NULL;
2683 /* a multi-sz has to have a null string terminator, i.e., the last
2684 string must be followed by two nulls */
2685 str_size = strlen(multi_sz) + 2;
2686 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2691 /* Change to byte units. */
2692 str_size *= sizeof(smb_ucs2_t);
2693 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2694 STR_TERMINATE | STR_NOALIGN);
2696 regval_ctr_delvalue(ctr, val_name);
2697 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2698 (char *) conv_strs, str_size);
2699 safe_free(conv_strs);
2703 /****************************************************************************
2704 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2706 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2707 * @return BOOL indicating success or failure
2708 ***************************************************************************/
2710 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2712 REGVAL_CTR *ctr = NULL;
2715 char *allocated_string = NULL;
2716 const char *ascii_str;
2719 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2720 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2721 ctr = &info2->data.keys[i].values;
2723 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2724 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2726 /* we make the assumption that the netbios name is the same
2727 as the DNS name sinc ethe former will be what we used to
2730 if ( get_mydnsdomname( dnssuffix ) )
2731 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2733 fstrcpy( longname, global_myname() );
2735 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2737 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2738 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2739 SAFE_FREE(allocated_string);
2741 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2742 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2743 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2744 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2745 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2746 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2747 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2748 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2749 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2751 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2752 (info2->attributes &
2753 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2755 switch (info2->attributes & 0x3) {
2757 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2760 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2763 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2766 ascii_str = "unknown";
2768 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2773 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2777 REGVAL_CTR *ctr=NULL;
2779 /* find the DsSpooler key */
2780 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2781 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2782 ctr = &info2->data.keys[i].values;
2784 regval_ctr_delvalue(ctr, "objectGUID");
2785 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2786 (char *) &guid, sizeof(struct uuid));
2789 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2790 NT_PRINTER_INFO_LEVEL *printer)
2794 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2795 char *srv_dn_utf8, **srv_cn_utf8;
2798 const char *attrs[] = {"objectGUID", NULL};
2800 WERROR win_rc = WERR_OK;
2802 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2804 /* figure out where to publish */
2805 ads_find_machine_acct(ads, &res, global_myname());
2807 /* We use ldap_get_dn here as we need the answer
2808 * in utf8 to call ldap_explode_dn(). JRA. */
2810 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2813 return WERR_SERVER_UNAVAILABLE;
2815 ads_msgfree(ads, res);
2816 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2818 ldap_memfree(srv_dn_utf8);
2820 return WERR_SERVER_UNAVAILABLE;
2822 /* Now convert to CH_UNIX. */
2823 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2824 ldap_memfree(srv_dn_utf8);
2825 ldap_memfree(srv_cn_utf8);
2827 return WERR_SERVER_UNAVAILABLE;
2829 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2830 ldap_memfree(srv_dn_utf8);
2831 ldap_memfree(srv_cn_utf8);
2834 return WERR_SERVER_UNAVAILABLE;
2837 ldap_memfree(srv_dn_utf8);
2838 ldap_memfree(srv_cn_utf8);
2840 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2841 printer->info_2->sharename, srv_dn);
2844 SAFE_FREE(srv_cn_0);
2846 /* build the ads mods */
2847 ctx = talloc_init("nt_printer_publish_ads");
2848 mods = ads_init_mods(ctx);
2850 get_local_printer_publishing_data(ctx, &mods,
2851 &printer->info_2->data);
2852 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2853 printer->info_2->sharename);
2856 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2857 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2858 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2860 if (!ADS_ERR_OK(ads_rc))
2861 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2863 talloc_destroy(ctx);
2865 /* retreive the guid and store it locally */
2866 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2868 ads_pull_guid(ads, res, &guid);
2869 ads_msgfree(ads, res);
2870 store_printer_guid(printer->info_2, guid);
2871 win_rc = mod_a_printer(printer, 2);
2878 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2879 NT_PRINTER_INFO_LEVEL *printer)
2883 char *prt_dn = NULL;
2885 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2887 /* remove the printer from the directory */
2888 ads_rc = ads_find_printer_on_server(ads, &res,
2889 printer->info_2->sharename, global_myname());
2891 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2892 prt_dn = ads_get_dn(ads, res);
2893 ads_rc = ads_del_dn(ads, prt_dn);
2894 ads_memfree(ads, prt_dn);
2897 ads_msgfree(ads, res);
2901 /****************************************************************************
2902 * Publish a printer in the directory
2904 * @param snum describing printer service
2905 * @return WERROR indicating status of publishing
2906 ***************************************************************************/
2908 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2911 ADS_STRUCT *ads = NULL;
2912 NT_PRINTER_INFO_LEVEL *printer = NULL;
2915 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2916 if (!W_ERROR_IS_OK(win_rc))
2920 case SPOOL_DS_PUBLISH:
2921 case SPOOL_DS_UPDATE:
2922 /* set the DsSpooler info and attributes */
2923 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2924 win_rc = WERR_NOMEM;
2928 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2930 case SPOOL_DS_UNPUBLISH:
2931 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2934 win_rc = WERR_NOT_SUPPORTED;
2938 win_rc = mod_a_printer(printer, 2);
2939 if (!W_ERROR_IS_OK(win_rc)) {
2940 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2944 ads = ads_init(NULL, NULL, NULL);
2946 DEBUG(3, ("ads_init() failed\n"));
2947 win_rc = WERR_SERVER_UNAVAILABLE;
2950 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2951 SAFE_FREE(ads->auth.password);
2952 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2955 /* ads_connect() will find the DC for us */
2956 ads_rc = ads_connect(ads);
2957 if (!ADS_ERR_OK(ads_rc)) {
2958 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2959 win_rc = WERR_ACCESS_DENIED;
2964 case SPOOL_DS_PUBLISH:
2965 case SPOOL_DS_UPDATE:
2966 win_rc = nt_printer_publish_ads(ads, printer);
2968 case SPOOL_DS_UNPUBLISH:
2969 win_rc = nt_printer_unpublish_ads(ads, printer);
2974 free_a_printer(&printer, 2);
2979 WERROR check_published_printers(void)
2982 ADS_STRUCT *ads = NULL;
2984 int n_services = lp_numservices();
2985 NT_PRINTER_INFO_LEVEL *printer = NULL;
2987 ads = ads_init(NULL, NULL, NULL);
2989 DEBUG(3, ("ads_init() failed\n"));
2990 return WERR_SERVER_UNAVAILABLE;
2992 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2993 SAFE_FREE(ads->auth.password);
2994 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2997 /* ads_connect() will find the DC for us */
2998 ads_rc = ads_connect(ads);
2999 if (!ADS_ERR_OK(ads_rc)) {
3000 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3002 return WERR_ACCESS_DENIED;
3005 for (snum = 0; snum < n_services; snum++) {
3006 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3009 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3010 lp_servicename(snum))) &&
3011 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3012 nt_printer_publish_ads(ads, printer);
3014 free_a_printer(&printer, 2);
3021 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3024 NT_PRINTER_INFO_LEVEL *printer = NULL;
3026 REGISTRY_VALUE *guid_val;
3030 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3032 if (!W_ERROR_IS_OK(win_rc) ||
3033 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3034 ((i = lookup_printerkey(&printer->info_2->data,
3035 SPOOL_DSSPOOLER_KEY)) < 0) ||
3036 !(ctr = &printer->info_2->data.keys[i].values) ||
3037 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3038 free_a_printer(&printer, 2);
3042 /* fetching printer guids really ought to be a separate function.. */
3043 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3044 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3046 free_a_printer(&printer, 2);
3050 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3055 WERROR check_published_printers(void)
3060 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3065 #endif /* HAVE_ADS */
3067 /****************************************************************************
3068 ***************************************************************************/
3070 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3072 NT_PRINTER_DATA *data;
3074 int removed_keys = 0;
3078 empty_slot = data->num_keys;
3081 return WERR_INVALID_PARAM;
3083 /* remove all keys */
3085 if ( !strlen(key) ) {
3086 for ( i=0; i<data->num_keys; i++ ) {
3087 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3088 data->keys[i].name));
3090 SAFE_FREE( data->keys[i].name );
3091 regval_ctr_destroy( &data->keys[i].values );
3094 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3097 SAFE_FREE( data->keys );
3098 ZERO_STRUCTP( data );
3103 /* remove a specific key (and all subkeys) */
3105 for ( i=0; i<data->num_keys; i++ ) {
3106 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3107 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3108 data->keys[i].name));
3110 SAFE_FREE( data->keys[i].name );
3111 regval_ctr_destroy( &data->keys[i].values );
3113 /* mark the slot as empty */
3115 ZERO_STRUCTP( &data->keys[i] );
3119 /* find the first empty slot */
3121 for ( i=0; i<data->num_keys; i++ ) {
3122 if ( !data->keys[i].name ) {
3129 if ( i == data->num_keys )
3130 /* nothing was removed */
3131 return WERR_INVALID_PARAM;
3133 /* move everything down */
3135 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3136 if ( data->keys[i].name ) {
3137 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3138 ZERO_STRUCTP( &data->keys[i] );
3146 data->num_keys -= removed_keys;
3148 /* sanity check to see if anything is left */
3150 if ( !data->num_keys ) {
3151 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3153 SAFE_FREE( data->keys );
3154 ZERO_STRUCTP( data );
3160 /****************************************************************************
3161 ***************************************************************************/
3163 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3165 WERROR result = WERR_OK;
3168 /* we must have names on non-zero length */
3170 if ( !key || !*key|| !value || !*value )
3171 return WERR_INVALID_NAME;
3173 /* find the printer key first */
3175 key_index = lookup_printerkey( &p2->data, key );
3176 if ( key_index == -1 )
3179 /* make sure the value exists so we can return the correct error code */
3181 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3182 return WERR_BADFILE;
3184 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3186 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3192 /****************************************************************************
3193 ***************************************************************************/
3195 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3196 uint32 type, uint8 *data, int real_len )
3198 WERROR result = WERR_OK;
3201 /* we must have names on non-zero length */
3203 if ( !key || !*key|| !value || !*value )
3204 return WERR_INVALID_NAME;
3206 /* find the printer key first */
3208 key_index = lookup_printerkey( &p2->data, key );
3209 if ( key_index == -1 )
3210 key_index = add_new_printer_key( &p2->data, key );
3212 if ( key_index == -1 )
3215 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3216 type, (const char *)data, real_len );
3218 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3219 key, value, type, real_len ));
3224 /****************************************************************************
3225 ***************************************************************************/
3227 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3231 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3234 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3237 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3240 /****************************************************************************
3241 Unpack a list of registry values frem the TDB
3242 ***************************************************************************/
3244 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3248 pstring string, valuename, keyname;
3252 REGISTRY_VALUE *regval_p;
3255 /* add the "PrinterDriverData" key first for performance reasons */
3257 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3259 /* loop and unpack the rest of the registry values */
3263 /* check to see if there are any more registry values */
3266 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3270 /* unpack the next regval */
3272 len += tdb_unpack(buf+len, buflen-len, "fdB",
3279 * break of the keyname from the value name.
3280 * Valuenames can have embedded '\'s so be careful.
3281 * only support one level of keys. See the
3282 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3286 str = strchr_m( string, '\\');
3288 /* Put in "PrinterDriverData" is no key specified */
3291 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3292 pstrcpy( valuename, string );
3296 pstrcpy( keyname, string );
3297 pstrcpy( valuename, str+1 );
3300 /* see if we need a new key */
3302 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3303 key_index = add_new_printer_key( printer_data, keyname );
3305 if ( key_index == -1 ) {
3306 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3311 /* add the new value */
3313 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3315 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3317 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3323 /****************************************************************************
3324 ***************************************************************************/
3326 static void map_to_os2_driver(fstring drivername)
3328 static BOOL initialised=False;
3329 static fstring last_from,last_to;
3330 char *mapfile = lp_os2_driver_map();
3331 char **lines = NULL;
3335 if (!strlen(drivername))
3342 *last_from = *last_to = 0;
3346 if (strequal(drivername,last_from)) {
3347 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3348 fstrcpy(drivername,last_to);
3352 lines = file_lines_load(mapfile, &numlines);
3353 if (numlines == 0) {
3354 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3358 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3360 for( i = 0; i < numlines; i++) {
3361 char *nt_name = lines[i];
3362 char *os2_name = strchr(nt_name,'=');
3369 while (isspace(*nt_name))
3372 if (!*nt_name || strchr("#;",*nt_name))
3376 int l = strlen(nt_name);
3377 while (l && isspace(nt_name[l-1])) {
3383 while (isspace(*os2_name))
3387 int l = strlen(os2_name);
3388 while (l && isspace(os2_name[l-1])) {
3394 if (strequal(nt_name,drivername)) {
3395 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3396 fstrcpy(last_from,drivername);
3397 fstrcpy(last_to,os2_name);
3398 fstrcpy(drivername,os2_name);
3399 file_lines_free(lines);
3404 file_lines_free(lines);
3407 /****************************************************************************
3408 Get a default printer info 2 struct.
3409 ****************************************************************************/
3410 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3413 NT_PRINTER_INFO_LEVEL_2 info;
3417 snum = lp_servicenumber(sharename);
3419 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3420 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3421 servername, sharename);
3422 fstrcpy(info.sharename, sharename);
3423 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3425 /* by setting the driver name to an empty string, a local NT admin
3426 can now run the **local** APW to install a local printer driver
3427 for a Samba shared printer in 2.2. Without this, drivers **must** be
3428 installed on the Samba server for NT clients --jerry */
3429 #if 0 /* JERRY --do not uncomment-- */
3430 if (!*info.drivername)
3431 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3435 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3437 pstrcpy(info.comment, "");
3438 fstrcpy(info.printprocessor, "winprint");
3439 fstrcpy(info.datatype, "RAW");
3441 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3443 info.starttime = 0; /* Minutes since 12:00am GMT */
3444 info.untiltime = 0; /* Minutes since 12:00am GMT */
3446 info.default_priority = 1;
3447 info.setuptime = (uint32)time(NULL);
3450 * I changed this as I think it is better to have a generic
3451 * DEVMODE than to crash Win2k explorer.exe --jerry
3452 * See the HP Deskjet 990c Win2k drivers for an example.
3454 * However the default devmode appears to cause problems
3455 * with the HP CLJ 8500 PCL driver. Hence the addition of
3456 * the "default devmode" parameter --jerry 22/01/2002
3459 if (lp_default_devmode(snum)) {
3460 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3464 info.devmode = NULL;
3467 /* This will get the current RPC talloc context, but we should be
3468 passing this as a parameter... fixme... JRA ! */
3470 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3473 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3475 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3483 free_nt_devicemode(&info.devmode);
3484 return WERR_ACCESS_DENIED;
3487 /****************************************************************************
3488 ****************************************************************************/
3489 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3492 NT_PRINTER_INFO_LEVEL_2 info;
3494 int snum = lp_servicenumber(sharename);
3495 TDB_DATA kbuf, dbuf;
3496 fstring printername;
3497 char adevice[MAXDEVICENAME];
3501 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3504 kbuf.dsize = strlen(key)+1;
3506 dbuf = tdb_fetch(tdb_printers, kbuf);
3508 return get_a_printer_2_default(info_ptr, servername, sharename);
3510 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3513 &info.default_priority,
3530 info.printprocessor,
3534 /* Samba has to have shared raw drivers. */
3535 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3536 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3538 /* Restore the stripped strings. */
3539 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3541 if ( lp_force_printername(snum) )
3542 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3544 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3546 fstrcpy(info.printername, printername);
3548 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3551 * Some client drivers freak out if there is a NULL devmode
3552 * (probably the driver is not checking before accessing
3553 * the devmode pointer) --jerry
3555 * See comments in get_a_printer_2_default()
3558 if (lp_default_devmode(snum) && !info.devmode) {
3559 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3561 info.devmode = construct_nt_devicemode(printername);
3564 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3566 fstrcpy(info.devmode->devicename, adevice);
3569 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3571 /* This will get the current RPC talloc context, but we should be
3572 passing this as a parameter... fixme... JRA ! */
3574 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3576 /* Fix for OS/2 drivers. */
3578 if (get_remote_arch() == RA_OS2)
3579 map_to_os2_driver(info.drivername);
3581 SAFE_FREE(dbuf.dptr);
3582 *info_ptr=memdup(&info, sizeof(info));
3584 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3585 sharename, info.printername, info.drivername));
3590 /****************************************************************************
3591 Debugging function, dump at level 6 the struct in the logs.
3592 ****************************************************************************/
3593 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3596 NT_PRINTER_INFO_LEVEL_2 *info2;
3598 DEBUG(106,("Dumping printer at level [%d]\n", level));
3603 if (printer->info_2 == NULL)
3607 info2=printer->info_2;
3609 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3610 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3611 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3612 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3613 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3614 DEBUGADD(106,("status:[%d]\n", info2->status));
3615 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3616 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3617 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3618 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3619 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3621 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3622 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3623 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3624 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3625 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3626 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3627 DEBUGADD(106,("location:[%s]\n", info2->location));
3628 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3629 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3630 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3631 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3637 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3645 /****************************************************************************
3646 Update the changeid time.
3647 This is SO NASTY as some drivers need this to change, others need it
3648 static. This value will change every second, and I must hope that this
3649 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3651 ****************************************************************************/
3653 static uint32 rev_changeid(void)
3657 get_process_uptime(&tv);
3660 /* Return changeid as msec since spooler restart */
3661 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3664 * This setting seems to work well but is too untested
3665 * to replace the above calculation. Left in for experiementation
3666 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3668 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3672 /********************************************************************
3673 Send a message to all smbds about the printer that just changed
3674 ********************************************************************/
3676 static BOOL send_printer_mod_msg( char* printername )
3678 int len = strlen(printername);
3683 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3686 /* spam everyone that we just changed this printer */
3688 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3694 * The function below are the high level ones.
3695 * only those ones must be called from the spoolss code.
3699 /****************************************************************************
3700 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3701 ****************************************************************************/
3703 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3707 dump_a_printer(printer, level);
3710 * invalidate cache for all open handles to this printer.
3711 * cache for a given handle will be updated on the next
3715 invalidate_printer_hnd_cache( printer->info_2->sharename );
3716 send_printer_mod_msg( printer->info_2->sharename );
3722 * Update the changestamp. Emperical tests show that the
3723 * ChangeID is always updated,but c_setprinter is
3724 * global spooler variable (not per printer).
3727 /* ChangeID **must** be increasing over the lifetime
3728 of client's spoolss service in order for the
3729 client's cache to show updates */
3731 printer->info_2->changeid = rev_changeid();
3734 * Because one day someone will ask:
3735 * NT->NT An admin connection to a remote
3736 * printer show changes imeediately in
3737 * the properities dialog
3739 * A non-admin connection will only show the
3740 * changes after viewing the properites page
3741 * 2 times. Seems to be related to a
3742 * race condition in the client between the spooler
3743 * updating the local cache and the Explorer.exe GUI
3744 * actually displaying the properties.
3746 * This is fixed in Win2k. admin/non-admin
3747 * connections both display changes immediately.
3752 result=update_a_printer_2(printer->info_2);
3757 result=WERR_UNKNOWN_LEVEL;
3764 /****************************************************************************
3765 Initialize printer devmode & data with previously saved driver init values.
3766 ****************************************************************************/
3768 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3772 TDB_DATA kbuf, dbuf;
3773 NT_PRINTER_INFO_LEVEL_2 info;
3779 * Delete any printer data 'values' already set. When called for driver
3780 * replace, there will generally be some, but during an add printer, there
3781 * should not be any (if there are delete them).
3784 delete_all_printer_data( info_ptr, "" );
3786 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3789 kbuf.dsize = strlen(key)+1;
3791 dbuf = tdb_fetch(tdb_drivers, kbuf);
3794 * When changing to a driver that has no init info in the tdb, remove
3795 * the previous drivers init info and leave the new on blank.
3797 free_nt_devicemode(&info_ptr->devmode);
3802 * Get the saved DEVMODE..
3805 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3808 * The saved DEVMODE contains the devicename from the printer used during
3809 * the initialization save. Change it to reflect the new printer.
3812 if ( info.devmode ) {
3813 ZERO_STRUCT(info.devmode->devicename);
3814 fstrcpy(info.devmode->devicename, info_ptr->printername);
3818 * NT/2k does not change out the entire DeviceMode of a printer
3819 * when changing the driver. Only the driverextra, private, &
3820 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3822 * Later examination revealed that Windows NT/2k does reset the
3823 * the printer's device mode, bit **only** when you change a
3824 * property of the device mode such as the page orientation.
3829 /* Bind the saved DEVMODE to the new the printer */
3831 free_nt_devicemode(&info_ptr->devmode);
3832 info_ptr->devmode = info.devmode;
3834 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3835 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3837 /* Add the printer data 'values' to the new printer */
3839 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3842 SAFE_FREE(dbuf.dptr);
3847 /****************************************************************************
3848 Initialize printer devmode & data with previously saved driver init values.
3849 When a printer is created using AddPrinter, the drivername bound to the
3850 printer is used to lookup previously saved driver initialization info, which
3851 is bound to the new printer.
3852 ****************************************************************************/
3854 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3856 BOOL result = False;
3860 result = set_driver_init_2(printer->info_2);
3864 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3872 /****************************************************************************
3873 Delete driver init data stored for a specified driver
3874 ****************************************************************************/
3876 BOOL del_driver_init(char *drivername)
3881 if (!drivername || !*drivername) {
3882 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3886 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3889 kbuf.dsize = strlen(key)+1;
3891 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3893 return (tdb_delete(tdb_drivers, kbuf) == 0);
3896 /****************************************************************************
3897 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3898 in the tdb. Note: this is different from the driver entry and the printer
3899 entry. There should be a single driver init entry for each driver regardless
3900 of whether it was installed from NT or 2K. Technically, they should be
3901 different, but they work out to the same struct.
3902 ****************************************************************************/
3904 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3908 int buflen, len, ret;
3909 TDB_DATA kbuf, dbuf;
3916 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3918 len += pack_values( &info->data, buf+len, buflen-len );
3923 tb = (char *)SMB_REALLOC(buf, len);
3925 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3935 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3938 kbuf.dsize = strlen(key)+1;
3942 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3946 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3950 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3951 info->sharename, info->drivername));
3956 /****************************************************************************
3957 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3958 ****************************************************************************/
3960 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3964 dump_a_printer(printer, level);
3968 result = update_driver_init_2(printer->info_2);
3978 /****************************************************************************
3979 Convert the printer data value, a REG_BINARY array, into an initialization
3980 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3981 got to keep the endians happy :).
3982 ****************************************************************************/
3984 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3986 BOOL result = False;
3990 ZERO_STRUCT(devmode);
3992 prs_init(&ps, 0, ctx, UNMARSHALL);
3993 ps.data_p = (char *)data;
3994 ps.buffer_size = data_len;
3996 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3997 result = convert_devicemode("", &devmode, &nt_devmode);
3999 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4004 /****************************************************************************
4005 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4007 1. Use the driver's config DLL to this UNC printername and:
4008 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4009 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4010 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4012 The last step triggers saving the "driver initialization" information for
4013 this printer into the tdb. Later, new printers that use this driver will
4014 have this initialization information bound to them. This simulates the
4015 driver initialization, as if it had run on the Samba server (as it would
4018 The Win32 client side code requirement sucks! But until we can run arbitrary
4019 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4021 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4022 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4023 about it and you will realize why. JRR 010720
4024 ****************************************************************************/
4026 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4028 WERROR status = WERR_OK;
4029 TALLOC_CTX *ctx = NULL;
4030 NT_DEVICEMODE *nt_devmode = NULL;
4031 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4034 * When the DEVMODE is already set on the printer, don't try to unpack it.
4036 DEBUG(8,("save_driver_init_2: Enter...\n"));
4038 if ( !printer->info_2->devmode && data_len ) {
4040 * Set devmode on printer info, so entire printer initialization can be
4044 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4047 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4048 status = WERR_NOMEM;
4052 ZERO_STRUCTP(nt_devmode);
4055 * The DEVMODE is held in the 'data' component of the param in raw binary.
4056 * Convert it to to a devmode structure
4058 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4059 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4060 status = WERR_INVALID_PARAM;
4064 printer->info_2->devmode = nt_devmode;
4068 * Pack up and add (or update) the DEVMODE and any current printer data to
4069 * a 'driver init' element in the tdb
4073 if ( update_driver_init(printer, 2) != 0 ) {
4074 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4075 status = WERR_NOMEM;
4080 * If driver initialization info was successfully saved, set the current
4081 * printer to match it. This allows initialization of the current printer
4082 * as well as the driver.
4084 status = mod_a_printer(printer, 2);
4085 if (!W_ERROR_IS_OK(status)) {
4086 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4087 printer->info_2->printername));
4091 talloc_destroy(ctx);
4092 free_nt_devicemode( &nt_devmode );
4094 printer->info_2->devmode = tmp_devmode;
4099 /****************************************************************************
4100 Update the driver init info (DEVMODE and specifics) for a printer
4101 ****************************************************************************/
4103 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4105 WERROR status = WERR_OK;
4109 status = save_driver_init_2( printer, data, data_len );
4112 status = WERR_UNKNOWN_LEVEL;
4119 /****************************************************************************
4120 Deep copy a NT_PRINTER_DATA
4121 ****************************************************************************/
4123 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4125 int i, j, num_vals, new_key_index;
4126 REGVAL_CTR *src_key, *dst_key;
4129 return NT_STATUS_NO_MEMORY;
4131 for ( i=0; i<src->num_keys; i++ ) {
4133 /* create a new instance of the printerkey in the destination
4134 printer_data object */
4136 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4137 dst_key = &dst->keys[new_key_index].values;
4139 src_key = &src->keys[i].values;
4140 num_vals = regval_ctr_numvals( src_key );
4142 /* dup the printer entire printer key */
4144 for ( j=0; j<num_vals; j++ ) {
4145 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4149 return NT_STATUS_OK;
4152 /****************************************************************************
4153 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4155 ****************************************************************************/
4157 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4159 NT_PRINTER_INFO_LEVEL_2 *copy;
4164 if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4167 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4169 /* malloc()'d members copied here */
4171 copy->devmode = dup_nt_devicemode( printer->devmode );
4173 ZERO_STRUCT( copy->data );
4174 copy_printer_data( ©->data, &printer->data );
4176 /* this is talloc()'d; very ugly that we have a structure that
4177 is half malloc()'d and half talloc()'d but that is the way
4178 that the PRINTER_INFO stuff is written right now. --jerry */
4180 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4185 /****************************************************************************
4186 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4188 Previously the code had a memory allocation problem because it always
4189 used the TALLOC_CTX from the Printer_entry*. This context lasts
4190 as a long as the original handle is open. So if the client made a lot
4191 of getprinter[data]() calls, the memory usage would climb. Now we use
4192 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4193 still use the Printer_entry->ctx for maintaining the cache copy though
4194 since that object must live as long as the handle by definition.
4197 ****************************************************************************/
4199 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4200 const char *sharename)
4203 NT_PRINTER_INFO_LEVEL *printer = NULL;
4208 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4212 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4213 DEBUG(0,("get_a_printer: malloc fail.\n"));
4216 ZERO_STRUCTP(printer);
4219 fstrcpy( servername, print_hnd->servername );
4221 fstrcpy( servername, "%L" );
4222 standard_sub_basic( "", servername, sizeof(servername)-1 );
4226 * check for cache first. A Printer handle cannot changed
4227 * to another printer object so we only check that the printer
4228 * is actually for a printer and that the printer_info pointer
4232 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4233 && print_hnd->printer_info )
4235 /* get_talloc_ctx() works here because we need a short
4236 lived talloc context */
4238 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4240 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4246 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4248 *pp_printer = printer;
4254 /* no cache for this handle; see if we can match one from another handle.
4255 Make sure to use a short lived talloc ctx */
4258 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4260 /* fail to disk if we don't have it with any open handle */
4262 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4263 result = get_a_printer_2(&printer->info_2, servername, sharename );
4265 /* we have a new printer now. Save it with this handle */
4267 if ( W_ERROR_IS_OK(result) ) {
4268 dump_a_printer(printer, level);
4270 /* save a copy in cache */
4271 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4272 if ( !print_hnd->printer_info )
4273 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4275 if ( print_hnd->printer_info ) {
4276 /* make sure to use the handle's talloc ctx here since
4277 the printer_2 object must last until the handle is closed */
4279 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4281 /* don't fail the lookup just because the cache update failed */
4282 if ( !print_hnd->printer_info->info_2 )
4283 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4286 *pp_printer = printer;
4294 result=WERR_UNKNOWN_LEVEL;
4298 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4303 /****************************************************************************
4304 Deletes a NT_PRINTER_INFO_LEVEL struct.
4305 ****************************************************************************/
4307 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4310 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4312 DEBUG(104,("freeing a printer at level [%d]\n", level));
4314 if (printer == NULL)
4319 if (printer->info_2 != NULL) {
4320 free_nt_printer_info_level_2(&printer->info_2);
4331 SAFE_FREE(*pp_printer);
4335 /****************************************************************************
4336 ****************************************************************************/
4337 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4340 DEBUG(104,("adding a printer at level [%d]\n", level));
4341 dump_a_printer_driver(driver, level);
4345 result=add_a_printer_driver_3(driver.info_3);
4349 result=add_a_printer_driver_6(driver.info_6);
4359 /****************************************************************************
4360 ****************************************************************************/
4362 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4363 fstring drivername, const char *architecture, uint32 version)
4369 /* Sometime we just want any version of the driver */
4371 if ( version == DRIVER_ANY_VERSION ) {
4372 /* look for Win2k first and then for NT4 */
4373 result = get_a_printer_driver_3(&driver->info_3, drivername,
4376 if ( !W_ERROR_IS_OK(result) ) {
4377 result = get_a_printer_driver_3( &driver->info_3,
4378 drivername, architecture, 2 );
4381 result = get_a_printer_driver_3(&driver->info_3, drivername,
4382 architecture, version);
4391 if (W_ERROR_IS_OK(result))
4392 dump_a_printer_driver(*driver, level);
4397 /****************************************************************************
4398 ****************************************************************************/
4399 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4406 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4407 if (driver.info_3 != NULL)
4409 info3=driver.info_3;
4410 SAFE_FREE(info3->dependentfiles);
4411 ZERO_STRUCTP(info3);
4421 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4422 if (driver.info_6 != NULL) {
4423 info6=driver.info_6;
4424 SAFE_FREE(info6->dependentfiles);
4425 SAFE_FREE(info6->previousnames);
4426 ZERO_STRUCTP(info6);
4442 /****************************************************************************
4443 Determine whether or not a particular driver is currently assigned
4445 ****************************************************************************/
4447 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4450 int n_services = lp_numservices();
4451 NT_PRINTER_INFO_LEVEL *printer = NULL;
4452 BOOL in_use = False;
4457 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4459 /* loop through the printers.tdb and check for the drivername */
4461 for (snum=0; snum<n_services && !in_use; snum++) {
4462 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4465 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4468 if ( strequal(info_3->name, printer->info_2->drivername) )
4471 free_a_printer( &printer, 2 );
4474 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4477 NT_PRINTER_DRIVER_INFO_LEVEL d;
4480 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4482 /* we can still remove the driver if there is one of
4483 "Windows NT x86" version 2 or 3 left */
4485 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4486 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4489 switch ( info_3->cversion ) {
4491 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4494 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4497 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4499 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4504 /* now check the error code */
4506 if ( W_ERROR_IS_OK(werr) ) {
4507 /* it's ok to remove the driver, we have other architctures left */
4509 free_a_printer_driver( d, 3 );
4513 /* report that the driver is not in use by default */
4519 /**********************************************************************
4520 Check to see if a ogiven file is in use by *info
4521 *********************************************************************/
4523 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4530 if ( strequal(file, info->driverpath) )
4533 if ( strequal(file, info->datafile) )
4536 if ( strequal(file, info->configfile) )
4539 if ( strequal(file, info->helpfile) )
4542 /* see of there are any dependent files to examine */
4544 if ( !info->dependentfiles )
4547 while ( *info->dependentfiles[i] ) {
4548 if ( strequal(file, info->dependentfiles[i]) )
4557 /**********************************************************************
4558 Utility function to remove the dependent file pointed to by the
4559 input parameter from the list
4560 *********************************************************************/
4562 static void trim_dependent_file( fstring files[], int idx )
4565 /* bump everything down a slot */
4567 while( *files[idx+1] ) {
4568 fstrcpy( files[idx], files[idx+1] );
4577 /**********************************************************************
4578 Check if any of the files used by src are also used by drv
4579 *********************************************************************/
4581 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4582 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4584 BOOL in_use = False;
4590 /* check each file. Remove it from the src structure if it overlaps */
4592 if ( drv_file_in_use(src->driverpath, drv) ) {
4594 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4595 fstrcpy( src->driverpath, "" );
4598 if ( drv_file_in_use(src->datafile, drv) ) {
4600 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4601 fstrcpy( src->datafile, "" );
4604 if ( drv_file_in_use(src->configfile, drv) ) {
4606 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4607 fstrcpy( src->configfile, "" );
4610 if ( drv_file_in_use(src->helpfile, drv) ) {
4612 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4613 fstrcpy( src->helpfile, "" );
4616 /* are there any dependentfiles to examine? */
4618 if ( !src->dependentfiles )
4621 while ( *src->dependentfiles[i] ) {
4622 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4624 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4625 trim_dependent_file( src->dependentfiles, i );
4633 /****************************************************************************
4634 Determine whether or not a particular driver files are currently being
4635 used by any other driver.
4637 Return value is True if any files were in use by other drivers
4638 and False otherwise.
4640 Upon return, *info has been modified to only contain the driver files
4641 which are not in use
4642 ****************************************************************************/
4644 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4649 fstring *list = NULL;
4650 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4655 version = info->cversion;
4657 /* loop over all driver versions */
4659 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4661 /* get the list of drivers */
4664 ndrivers = get_ntdrivers(&list, info->environment, version);
4666 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4667 ndrivers, info->environment, version));
4669 /* check each driver for overlap in files */
4671 for (i=0; i<ndrivers; i++) {
4672 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4674 ZERO_STRUCT(driver);
4676 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4681 /* check if d2 uses any files from d1 */
4682 /* only if this is a different driver than the one being deleted */
4684 if ( !strequal(info->name, driver.info_3->name) ) {
4685 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4686 free_a_printer_driver(driver, 3);
4692 free_a_printer_driver(driver, 3);
4697 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4699 driver.info_3 = info;
4701 if ( DEBUGLEVEL >= 20 )
4702 dump_a_printer_driver( driver, 3 );
4707 /****************************************************************************
4708 Actually delete the driver files. Make sure that
4709 printer_driver_files_in_use() return False before calling
4711 ****************************************************************************/
4713 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4717 connection_struct *conn;
4727 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4730 * Connect to the print$ share under the same account as the
4731 * user connected to the rpc pipe. Note we must be root to
4735 null_pw = data_blob( NULL, 0 );
4736 fstrcpy(res_type, "A:");
4738 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4742 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4746 /* Save who we are - we are temporarily becoming the connection user. */
4748 if ( !become_user(conn, conn->vuid) ) {
4749 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4753 /* now delete the files; must strip the '\print$' string from
4756 if ( *info_3->driverpath ) {
4757 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4758 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4759 DEBUG(10,("deleting driverfile [%s]\n", s));
4760 unlink_internals(conn, 0, s);
4764 if ( *info_3->configfile ) {
4765 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4766 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4767 DEBUG(10,("deleting configfile [%s]\n", s));
4768 unlink_internals(conn, 0, s);
4772 if ( *info_3->datafile ) {
4773 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4774 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4775 DEBUG(10,("deleting datafile [%s]\n", s));
4776 unlink_internals(conn, 0, s);
4780 if ( *info_3->helpfile ) {
4781 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4782 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4783 DEBUG(10,("deleting helpfile [%s]\n", s));
4784 unlink_internals(conn, 0, s);
4788 /* check if we are done removing files */
4790 if ( info_3->dependentfiles ) {
4791 while ( *info_3->dependentfiles[i] ) {
4794 /* bypass the "\print$" portion of the path */
4796 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4797 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4798 DEBUG(10,("deleting dependent file [%s]\n", file));
4799 unlink_internals(conn, 0, file );
4811 /****************************************************************************
4812 Remove a printer driver from the TDB. This assumes that the the driver was
4813 previously looked up.
4814 ***************************************************************************/
4816 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4817 uint32 version, BOOL delete_files )
4821 TDB_DATA kbuf, dbuf;
4822 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4824 /* delete the tdb data first */
4826 arch = get_short_archi(info_3->environment);
4827 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4828 arch, version, info_3->name);
4830 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4831 key, delete_files ? "TRUE" : "FALSE" ));
4833 ctr.info_3 = info_3;
4834 dump_a_printer_driver( ctr, 3 );
4837 kbuf.dsize=strlen(key)+1;
4839 /* check if the driver actually exists for this environment */
4841 dbuf = tdb_fetch( tdb_drivers, kbuf );
4843 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4844 return WERR_UNKNOWN_PRINTER_DRIVER;
4847 SAFE_FREE( dbuf.dptr );
4849 /* ok... the driver exists so the delete should return success */
4851 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4852 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4853 return WERR_ACCESS_DENIED;
4857 * now delete any associated files if delete_files == True
4858 * even if this part failes, we return succes because the
4859 * driver doesn not exist any more
4863 delete_driver_files( info_3, user );
4866 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4871 /****************************************************************************
4872 Store a security desc for a printer.
4873 ****************************************************************************/
4875 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4877 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4878 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4880 TALLOC_CTX *mem_ctx = NULL;
4884 mem_ctx = talloc_init("nt_printing_setsec");
4885 if (mem_ctx == NULL)
4888 /* The old owner and group sids of the security descriptor are not
4889 present when new ACEs are added or removed by changing printer
4890 permissions through NT. If they are NULL in the new security
4891 descriptor then copy them over from the old one. */
4893 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4894 DOM_SID *owner_sid, *group_sid;
4895 SEC_ACL *dacl, *sacl;
4896 SEC_DESC *psd = NULL;
4899 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4901 /* Pick out correct owner and group sids */
4903 owner_sid = secdesc_ctr->sec->owner_sid ?
4904 secdesc_ctr->sec->owner_sid :
4905 old_secdesc_ctr->sec->owner_sid;
4907 group_sid = secdesc_ctr->sec->grp_sid ?
4908 secdesc_ctr->sec->grp_sid :
4909 old_secdesc_ctr->sec->grp_sid;
4911 dacl = secdesc_ctr->sec->dacl ?
4912 secdesc_ctr->sec->dacl :
4913 old_secdesc_ctr->sec->dacl;
4915 sacl = secdesc_ctr->sec->sacl ?
4916 secdesc_ctr->sec->sacl :
4917 old_secdesc_ctr->sec->sacl;
4919 /* Make a deep copy of the security descriptor */
4921 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4922 owner_sid, group_sid,
4927 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4930 if (!new_secdesc_ctr) {
4931 new_secdesc_ctr = secdesc_ctr;
4934 /* Store the security descriptor in a tdb */
4936 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4937 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4939 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4941 status = WERR_BADFUNC;
4945 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4947 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4950 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4951 status = WERR_BADFUNC;
4954 /* Free malloc'ed memory */
4960 talloc_destroy(mem_ctx);
4964 /****************************************************************************
4965 Construct a default security descriptor buffer for a printer.
4966 ****************************************************************************/
4968 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4970 SEC_ACE ace[5]; /* max number of ace entries */
4973 SEC_ACL *psa = NULL;
4974 SEC_DESC_BUF *sdb = NULL;
4975 SEC_DESC *psd = NULL;
4979 /* Create an ACE where Everyone is allowed to print */
4981 init_sec_access(&sa, PRINTER_ACE_PRINT);
4982 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4983 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4985 /* Add the domain admins group if we are a DC */
4988 DOM_SID domadmins_sid;
4990 sid_copy(&domadmins_sid, get_global_sam_sid());
4991 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
4993 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4994 init_sec_ace(&ace[i++], &domadmins_sid,
4995 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
4996 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
4997 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4998 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5000 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5001 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5003 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5004 init_sec_ace(&ace[i++], &adm_sid,
5005 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5006 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5007 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5008 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5011 /* add BUILTIN\Administrators as FULL CONTROL */
5013 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5014 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5015 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5016 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5017 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5018 SEC_ACE_TYPE_ACCESS_ALLOWED,
5019 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5021 /* Make the security descriptor owned by the BUILTIN\Administrators */
5023 /* The ACL revision number in rpc_secdesc.h differs from the one
5024 created by NT when setting ACE entries in printer
5025 descriptors. NT4 complains about the property being edited by a
5028 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5029 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5030 &global_sid_Builtin_Administrators,
5031 &global_sid_Builtin_Administrators,
5032 NULL, psa, &sd_size);
5036 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5040 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5042 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5043 (unsigned int)sd_size));
5048 /****************************************************************************
5049 Get a security desc for a printer.
5050 ****************************************************************************/
5052 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
5058 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
5059 printername = temp + 1;
5062 /* Fetch security descriptor from tdb */
5064 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
5066 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5067 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5069 DEBUG(4,("using default secdesc for %s\n", printername));
5071 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5075 /* Save default security descriptor for later */
5077 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5078 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5080 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5081 tdb_prs_store(tdb_printers, key, &ps);
5088 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5089 this security descriptor has been created when winbindd was
5090 down. Take ownership of security descriptor. */
5092 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5095 /* Change sd owner to workgroup administrator */
5097 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5098 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5099 SEC_DESC *psd = NULL;
5104 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5106 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5108 (*secdesc_ctr)->sec->grp_sid,
5109 (*secdesc_ctr)->sec->sacl,
5110 (*secdesc_ctr)->sec->dacl,
5113 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5115 /* Swap with other one */
5117 *secdesc_ctr = new_secdesc_ctr;
5121 nt_printing_setsec(printername, *secdesc_ctr);
5125 if (DEBUGLEVEL >= 10) {
5126 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5129 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5130 printername, the_acl->num_aces));
5132 for (i = 0; i < the_acl->num_aces; i++) {
5135 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5137 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5138 the_acl->ace[i].type, the_acl->ace[i].flags,
5139 the_acl->ace[i].info.mask));
5149 1: level not implemented
5150 2: file doesn't exist
5151 3: can't allocate memory
5152 4: can't free memory
5153 5: non existant struct
5157 A printer and a printer driver are 2 different things.
5158 NT manages them separatelly, Samba does the same.
5159 Why ? Simply because it's easier and it makes sense !
5161 Now explanation: You have 3 printers behind your samba server,
5162 2 of them are the same make and model (laser A and B). But laser B
5163 has an 3000 sheet feeder and laser A doesn't such an option.
5164 Your third printer is an old dot-matrix model for the accounting :-).
5166 If the /usr/local/samba/lib directory (default dir), you will have
5167 5 files to describe all of this.
5169 3 files for the printers (1 by printer):
5172 NTprinter_accounting
5173 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5174 NTdriver_printer model X
5175 NTdriver_printer model Y
5177 jfm: I should use this comment for the text file to explain
5178 same thing for the forms BTW.
5179 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5183 /* Convert generic access rights to printer object specific access rights.
5184 It turns out that NT4 security descriptors use generic access rights and
5185 NT5 the object specific ones. */
5187 void map_printer_permissions(SEC_DESC *sd)
5191 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5192 se_map_generic(&sd->dacl->ace[i].info.mask,
5193 &printer_generic_mapping);
5197 /****************************************************************************
5198 Check a user has permissions to perform the given operation. We use the
5199 permission constants defined in include/rpc_spoolss.h to check the various
5200 actions we perform when checking printer access.
5202 PRINTER_ACCESS_ADMINISTER:
5203 print_queue_pause, print_queue_resume, update_printer_sec,
5204 update_printer, spoolss_addprinterex_level_2,
5205 _spoolss_setprinterdata
5210 JOB_ACCESS_ADMINISTER:
5211 print_job_delete, print_job_pause, print_job_resume,
5214 Try access control in the following order (for performance reasons):
5215 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5216 2) check security descriptor (bit comparisons in memory)
5217 3) "printer admins" (may result in numerous calls to winbind)
5219 ****************************************************************************/
5220 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5222 SEC_DESC_BUF *secdesc = NULL;
5223 uint32 access_granted;
5227 TALLOC_CTX *mem_ctx = NULL;
5228 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5230 /* If user is NULL then use the current_user structure */
5233 user = ¤t_user;
5235 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5237 if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5241 /* Get printer name */
5243 pname = PRINTERNAME(snum);
5245 if (!pname || !*pname) {
5250 /* Get printer security descriptor */
5252 if(!(mem_ctx = talloc_init("print_access_check"))) {
5257 nt_printing_getsec(mem_ctx, pname, &secdesc);
5259 if (access_type == JOB_ACCESS_ADMINISTER) {
5260 SEC_DESC_BUF *parent_secdesc = secdesc;
5262 /* Create a child security descriptor to check permissions
5263 against. This is because print jobs are child objects
5264 objects of a printer. */
5266 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5268 /* Now this is the bit that really confuses me. The access
5269 type needs to be changed from JOB_ACCESS_ADMINISTER to
5270 PRINTER_ACCESS_ADMINISTER for this to work. Something
5271 to do with the child (job) object becoming like a
5274 access_type = PRINTER_ACCESS_ADMINISTER;
5279 map_printer_permissions(secdesc->sec);
5281 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5282 &access_granted, &status);
5284 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5286 /* see if we need to try the printer admin list */
5288 if ( access_granted == 0 ) {
5289 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5293 talloc_destroy(mem_ctx);
5301 /****************************************************************************
5302 Check the time parameters allow a print operation.
5303 *****************************************************************************/
5305 BOOL print_time_access_check(int snum)
5307 NT_PRINTER_INFO_LEVEL *printer = NULL;
5309 time_t now = time(NULL);
5313 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5316 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5320 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5322 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5325 free_a_printer(&printer, 2);
5333 /****************************************************************************
5334 Fill in the servername sent in the _spoolss_open_printer_ex() call
5335 ****************************************************************************/
5336 char* get_server_name( Printer_entry *printer )
5338 return printer->servername;