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 static pid_t local_pid;
416 const char *vstring = "INFO/version";
420 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
424 tdb_close(tdb_drivers);
425 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
427 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
428 lock_path("ntdrivers.tdb"), strerror(errno) ));
433 tdb_close(tdb_printers);
434 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
436 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
437 lock_path("ntprinters.tdb"), strerror(errno) ));
442 tdb_close(tdb_forms);
443 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
445 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
446 lock_path("ntforms.tdb"), strerror(errno) ));
450 local_pid = sys_getpid();
452 /* handle a Samba upgrade */
453 tdb_lock_bystring(tdb_drivers, vstring, 0);
455 /* ---------------- Start Lock Region ---------------- */
457 /* Cope with byte-reversed older versions of the db. */
458 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
460 if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
462 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
463 /* Written on a bigendian machine with old fetch_int code. Save as le. */
464 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
465 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
466 vers_id = NTDRIVERS_DATABASE_VERSION_3;
469 if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
471 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
472 if (!upgrade_to_version_3())
475 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
477 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
480 /* at this point we know that the database is at version 3 so upgrade to v4 */
482 if ( !upgrade_to_version_4() )
484 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
487 /* ---------------- End Lock Region ------------------ */
489 tdb_unlock_bystring(tdb_drivers, vstring);
491 update_c_setprinter(True);
494 * register callback to handle updating printers as new
495 * drivers are installed
498 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
501 * register callback to handle updating printer data
502 * when a driver is initialized
505 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
508 * register callback to handle invalidating the printer cache
509 * between smbd processes.
512 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
514 /* of course, none of the message callbacks matter if you don't
515 tell messages.c that you interested in receiving PRINT_GENERAL
516 msgs. This is done in claim_connection() */
519 if ( lp_security() == SEC_ADS ) {
520 win_rc = check_published_printers();
521 if (!W_ERROR_IS_OK(win_rc))
522 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
528 /*******************************************************************
529 Function to allow filename parsing "the old way".
530 ********************************************************************/
532 static BOOL driver_unix_convert(char *name,connection_struct *conn,
533 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
536 unix_clean_name(name);
537 trim_string(name,"/","/");
538 return unix_convert(name, conn, saved_last_component, bad_path, pst);
541 /*******************************************************************
542 tdb traversal function for counting printers.
543 ********************************************************************/
545 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
546 TDB_DATA data, void *context)
548 int *printer_count = (int*)context;
550 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
552 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
558 /*******************************************************************
559 Update the spooler global c_setprinter. This variable is initialized
560 when the parent smbd starts with the number of existing printers. It
561 is monotonically increased by the current number of printers *after*
562 each add or delete printer RPC. Only Microsoft knows why... JRR020119
563 ********************************************************************/
565 uint32 update_c_setprinter(BOOL initialize)
568 int32 printer_count = 0;
570 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
572 /* Traverse the tdb, counting the printers */
573 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
575 /* If initializing, set c_setprinter to current printers count
576 * otherwise, bump it by the current printer count
579 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
581 c_setprinter = printer_count;
583 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
584 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
586 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
588 return (uint32)c_setprinter;
591 /*******************************************************************
592 Get the spooler global c_setprinter, accounting for initialization.
593 ********************************************************************/
595 uint32 get_c_setprinter(void)
597 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
599 if (c_setprinter == (int32)-1)
600 c_setprinter = update_c_setprinter(True);
602 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
604 return (uint32)c_setprinter;
607 /****************************************************************************
608 Get builtin form struct list.
609 ****************************************************************************/
611 int get_builtin_ntforms(nt_forms_struct **list)
613 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
614 return sizeof(default_forms) / sizeof(default_forms[0]);
617 /****************************************************************************
618 get a builtin form struct
619 ****************************************************************************/
621 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
625 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
626 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
627 count = sizeof(default_forms) / sizeof(default_forms[0]);
628 for (i=0;i<count;i++) {
629 if (strequal(form_name,default_forms[i].name)) {
630 DEBUGADD(6,("Found builtin form %s \n", form_name));
631 memcpy(form,&default_forms[i],sizeof(*form));
639 /****************************************************************************
640 get a form struct list
641 ****************************************************************************/
642 int get_ntforms(nt_forms_struct **list)
644 TDB_DATA kbuf, newkey, dbuf;
646 nt_forms_struct form;
651 for (kbuf = tdb_firstkey(tdb_forms);
653 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
655 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
658 dbuf = tdb_fetch(tdb_forms, kbuf);
662 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
663 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
664 &i, &form.flag, &form.width, &form.length, &form.left,
665 &form.top, &form.right, &form.bottom);
666 SAFE_FREE(dbuf.dptr);
667 if (ret != dbuf.dsize)
670 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
672 DEBUG(0,("get_ntforms: Realloc fail.\n"));
684 /****************************************************************************
685 write a form struct list
686 ****************************************************************************/
687 int write_ntforms(nt_forms_struct **list, int number)
694 for (i=0;i<number;i++) {
695 /* save index, so list is rebuilt in correct order */
696 len = tdb_pack(buf, sizeof(buf), "dddddddd",
697 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
698 (*list)[i].left, (*list)[i].top, (*list)[i].right,
700 if (len > sizeof(buf)) break;
701 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
702 kbuf.dsize = strlen(key)+1;
706 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
712 /****************************************************************************
713 add a form struct at the end of the list
714 ****************************************************************************/
715 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
723 * NT tries to add forms even when
724 * they are already in the base
725 * only update the values if already present
730 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
731 for (n=0; n<*count; n++) {
732 if ( strequal((*list)[n].name, form_name) ) {
739 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
740 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
744 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
748 (*list)[n].flag=form->flags;
749 (*list)[n].width=form->size_x;
750 (*list)[n].length=form->size_y;
751 (*list)[n].left=form->left;
752 (*list)[n].top=form->top;
753 (*list)[n].right=form->right;
754 (*list)[n].bottom=form->bottom;
756 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
757 update ? "updated" : "added", form_name));
762 /****************************************************************************
763 Delete a named form struct.
764 ****************************************************************************/
766 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
775 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
777 for (n=0; n<*count; n++) {
778 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
779 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
785 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
786 *ret = WERR_INVALID_PARAM;
790 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
791 kbuf.dsize = strlen(key)+1;
793 if (tdb_delete(tdb_forms, kbuf) != 0) {
801 /****************************************************************************
802 Update a form struct.
803 ****************************************************************************/
805 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
809 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
811 DEBUG(106, ("[%s]\n", form_name));
812 for (n=0; n<count; n++) {
813 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
814 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
818 if (n==count) return;
820 (*list)[n].flag=form->flags;
821 (*list)[n].width=form->size_x;
822 (*list)[n].length=form->size_y;
823 (*list)[n].left=form->left;
824 (*list)[n].top=form->top;
825 (*list)[n].right=form->right;
826 (*list)[n].bottom=form->bottom;
829 /****************************************************************************
830 Get the nt drivers list.
831 Traverse the database and look-up the matching names.
832 ****************************************************************************/
833 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
836 const char *short_archi;
839 TDB_DATA kbuf, newkey;
841 short_archi = get_short_archi(architecture);
842 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
844 for (kbuf = tdb_firstkey(tdb_drivers);
846 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
848 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
851 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
852 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
857 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
864 /****************************************************************************
865 function to do the mapping between the long architecture name and
867 ****************************************************************************/
868 const char *get_short_archi(const char *long_archi)
872 DEBUG(107,("Getting architecture dependant directory\n"));
875 } while ( (archi_table[i].long_archi!=NULL ) &&
876 StrCaseCmp(long_archi, archi_table[i].long_archi) );
878 if (archi_table[i].long_archi==NULL) {
879 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
883 /* this might be client code - but shouldn't this be an fstrcpy etc? */
886 DEBUGADD(108,("index: [%d]\n", i));
887 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
888 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
890 return archi_table[i].short_archi;
893 /****************************************************************************
894 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
895 There are two case to be covered here: PE (Portable Executable) and NE (New
896 Executable) files. Both files support the same INFO structure, but PE files
897 store the signature in unicode, and NE files store it as !unicode.
898 returns -1 on error, 1 on version info found, and 0 on no version info found.
899 ****************************************************************************/
901 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
907 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
908 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
909 fname, PE_HEADER_SIZE));
913 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
914 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
915 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
916 fname, (unsigned long)byte_count));
917 goto no_version_info;
920 /* Is this really a DOS header? */
921 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
922 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
923 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
924 goto no_version_info;
927 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
928 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
929 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
931 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
932 goto no_version_info;
935 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
936 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
937 fname, (unsigned long)byte_count));
938 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
939 goto no_version_info;
942 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
943 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
944 unsigned int num_sections;
945 unsigned int section_table_bytes;
947 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
948 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
949 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
950 /* At this point, we assume the file is in error. It still could be somthing
951 * else besides a PE file, but it unlikely at this point.
956 /* get the section table */
957 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
958 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
959 if (section_table_bytes == 0)
963 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
964 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
965 fname, section_table_bytes));
969 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
970 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
971 fname, (unsigned long)byte_count));
975 /* Iterate the section table looking for the resource section ".rsrc" */
976 for (i = 0; i < num_sections; i++) {
977 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
979 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
980 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
981 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
983 if (section_bytes == 0)
987 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
988 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
989 fname, section_bytes));
993 /* Seek to the start of the .rsrc section info */
994 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
995 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1000 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1001 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1002 fname, (unsigned long)byte_count));
1006 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1009 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1010 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1011 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1012 /* Align to next long address */
1013 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1015 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1016 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1017 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1019 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1020 fname, *major, *minor,
1021 (*major>>16)&0xffff, *major&0xffff,
1022 (*minor>>16)&0xffff, *minor&0xffff));
1031 /* Version info not found, fall back to origin date/time */
1032 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1036 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1037 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1038 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1039 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1040 /* At this point, we assume the file is in error. It still could be somthing
1041 * else besides a NE file, but it unlikely at this point. */
1045 /* Allocate a bit more space to speed up things */
1047 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1048 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1049 fname, PE_HEADER_SIZE));
1053 /* This is a HACK! I got tired of trying to sort through the messy
1054 * 'NE' file format. If anyone wants to clean this up please have at
1055 * it, but this works. 'NE' files will eventually fade away. JRR */
1056 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1057 /* Cover case that should not occur in a well formed 'NE' .dll file */
1058 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1060 for(i=0; i<byte_count; i++) {
1061 /* Fast skip past data that can't possibly match */
1062 if (buf[i] != 'V') continue;
1064 /* Potential match data crosses buf boundry, move it to beginning
1065 * of buf, and fill the buf with as much as it will hold. */
1066 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1069 memcpy(buf, &buf[i], byte_count-i);
1070 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1071 (byte_count-i))) < 0) {
1073 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1078 byte_count = bc + (byte_count - i);
1079 if (byte_count<VS_VERSION_INFO_SIZE) break;
1084 /* Check that the full signature string and the magic number that
1085 * follows exist (not a perfect solution, but the chances that this
1086 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1087 * twice, as it is simpler to read the code. */
1088 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1089 /* Compute skip alignment to next long address */
1090 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1091 sizeof(VS_SIGNATURE)) & 3;
1092 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1094 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1095 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1096 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1097 fname, *major, *minor,
1098 (*major>>16)&0xffff, *major&0xffff,
1099 (*minor>>16)&0xffff, *minor&0xffff));
1106 /* Version info not found, fall back to origin date/time */
1107 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1112 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1113 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1114 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1125 /****************************************************************************
1126 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1127 share one or more files. During the MS installation process files are checked
1128 to insure that only a newer version of a shared file is installed over an
1129 older version. There are several possibilities for this comparison. If there
1130 is no previous version, the new one is newer (obviously). If either file is
1131 missing the version info structure, compare the creation date (on Unix use
1132 the modification date). Otherwise chose the numerically larger version number.
1133 ****************************************************************************/
1135 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1137 BOOL use_version = True;
1142 time_t new_create_time;
1146 time_t old_create_time;
1150 files_struct *fsp = NULL;
1152 SMB_STRUCT_STAT stat_buf;
1155 SET_STAT_INVALID(st);
1156 SET_STAT_INVALID(stat_buf);
1157 new_create_time = (time_t)0;
1158 old_create_time = (time_t)0;
1160 /* Get file version info (if available) for previous file (if it exists) */
1161 pstrcpy(filepath, old_file);
1163 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1165 fsp = open_file_shared(conn, filepath, &stat_buf,
1166 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1167 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1168 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1170 /* Old file not found, so by definition new file is in fact newer */
1171 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1176 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1177 if (ret == -1) goto error_exit;
1180 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1182 use_version = False;
1183 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1184 old_create_time = st.st_mtime;
1185 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1188 close_file(fsp, True);
1190 /* Get file version info (if available) for new file */
1191 pstrcpy(filepath, new_file);
1192 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1194 fsp = open_file_shared(conn, filepath, &stat_buf,
1195 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1196 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1197 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1199 /* New file not found, this shouldn't occur if the caller did its job */
1200 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1205 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1206 if (ret == -1) goto error_exit;
1209 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1211 use_version = False;
1212 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1213 new_create_time = st.st_mtime;
1214 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1217 close_file(fsp, True);
1219 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1220 /* Compare versions and choose the larger version number */
1221 if (new_major > old_major ||
1222 (new_major == old_major && new_minor > old_minor)) {
1224 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1228 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1233 /* Compare modification time/dates and choose the newest time/date */
1234 if (new_create_time > old_create_time) {
1235 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1239 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1246 close_file(fsp, True);
1250 /****************************************************************************
1251 Determine the correct cVersion associated with an architecture and driver
1252 ****************************************************************************/
1253 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1254 struct current_user *user, WERROR *perr)
1263 files_struct *fsp = NULL;
1266 connection_struct *conn;
1268 SET_STAT_INVALID(st);
1270 *perr = WERR_INVALID_PARAM;
1272 /* If architecture is Windows 95/98/ME, the version is always 0. */
1273 if (strcmp(architecture, "WIN40") == 0) {
1274 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1280 * Connect to the print$ share under the same account as the user connected
1281 * to the rpc pipe. Note we must still be root to do this.
1284 /* Null password is ok - we are already an authenticated user... */
1285 null_pw = data_blob(NULL, 0);
1286 fstrcpy(res_type, "A:");
1288 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1292 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1293 *perr = ntstatus_to_werror(nt_status);
1297 /* We are temporarily becoming the connection user. */
1298 if (!become_user(conn, user->vuid)) {
1299 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1300 *perr = WERR_ACCESS_DENIED;
1304 /* Open the driver file (Portable Executable format) and determine the
1305 * deriver the cversion. */
1306 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1308 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1310 fsp = open_file_shared(conn, driverpath, &st,
1311 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1312 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1313 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1315 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1316 driverpath, errno));
1317 *perr = WERR_ACCESS_DENIED;
1323 int ret = get_file_version(fsp, driverpath, &major, &minor);
1324 if (ret == -1) goto error_exit;
1327 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1332 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1333 * for more details. Version in this case is not just the version of the
1334 * file, but the version in the sense of kernal mode (2) vs. user mode
1335 * (3) drivers. Other bits of the version fields are the version info.
1338 cversion = major & 0x0000ffff;
1340 case 2: /* WinNT drivers */
1341 case 3: /* Win2K drivers */
1345 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1346 driverpath, cversion));
1350 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1351 driverpath, major, minor));
1354 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1355 driverpath, cversion));
1357 close_file(fsp, True);
1358 close_cnum(conn, user->vuid);
1367 close_file(fsp, True);
1369 close_cnum(conn, user->vuid);
1374 /****************************************************************************
1375 ****************************************************************************/
1376 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1377 struct current_user *user)
1379 const char *architecture;
1385 /* clean up the driver name.
1386 * we can get .\driver.dll
1387 * or worse c:\windows\system\driver.dll !
1389 /* using an intermediate string to not have overlaping memcpy()'s */
1390 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1391 fstrcpy(new_name, p+1);
1392 fstrcpy(driver->driverpath, new_name);
1395 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1396 fstrcpy(new_name, p+1);
1397 fstrcpy(driver->datafile, new_name);
1400 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1401 fstrcpy(new_name, p+1);
1402 fstrcpy(driver->configfile, new_name);
1405 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1406 fstrcpy(new_name, p+1);
1407 fstrcpy(driver->helpfile, new_name);
1410 if (driver->dependentfiles) {
1411 for (i=0; *driver->dependentfiles[i]; i++) {
1412 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1413 fstrcpy(new_name, p+1);
1414 fstrcpy(driver->dependentfiles[i], new_name);
1419 architecture = get_short_archi(driver->environment);
1421 /* jfm:7/16/2000 the client always sends the cversion=0.
1422 * The server should check which version the driver is by reading
1423 * the PE header of driver->driverpath.
1425 * For Windows 95/98 the version is 0 (so the value sent is correct)
1426 * For Windows NT (the architecture doesn't matter)
1427 * NT 3.1: cversion=0
1428 * NT 3.5/3.51: cversion=1
1432 if ((driver->cversion = get_correct_cversion( architecture,
1433 driver->driverpath, user, &err)) == -1)
1439 /****************************************************************************
1440 ****************************************************************************/
1441 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1443 const char *architecture;
1449 /* clean up the driver name.
1450 * we can get .\driver.dll
1451 * or worse c:\windows\system\driver.dll !
1453 /* using an intermediate string to not have overlaping memcpy()'s */
1454 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1455 fstrcpy(new_name, p+1);
1456 fstrcpy(driver->driverpath, new_name);
1459 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1460 fstrcpy(new_name, p+1);
1461 fstrcpy(driver->datafile, new_name);
1464 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1465 fstrcpy(new_name, p+1);
1466 fstrcpy(driver->configfile, new_name);
1469 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1470 fstrcpy(new_name, p+1);
1471 fstrcpy(driver->helpfile, new_name);
1474 if (driver->dependentfiles) {
1475 for (i=0; *driver->dependentfiles[i]; i++) {
1476 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1477 fstrcpy(new_name, p+1);
1478 fstrcpy(driver->dependentfiles[i], new_name);
1483 architecture = get_short_archi(driver->environment);
1485 /* jfm:7/16/2000 the client always sends the cversion=0.
1486 * The server should check which version the driver is by reading
1487 * the PE header of driver->driverpath.
1489 * For Windows 95/98 the version is 0 (so the value sent is correct)
1490 * For Windows NT (the architecture doesn't matter)
1491 * NT 3.1: cversion=0
1492 * NT 3.5/3.51: cversion=1
1496 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1502 /****************************************************************************
1503 ****************************************************************************/
1504 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1505 uint32 level, struct current_user *user)
1510 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1511 driver=driver_abstract.info_3;
1512 return clean_up_driver_struct_level_3(driver, user);
1516 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1517 driver=driver_abstract.info_6;
1518 return clean_up_driver_struct_level_6(driver, user);
1521 return WERR_INVALID_PARAM;
1525 /****************************************************************************
1526 This function sucks and should be replaced. JRA.
1527 ****************************************************************************/
1529 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1531 dst->cversion = src->version;
1533 fstrcpy( dst->name, src->name);
1534 fstrcpy( dst->environment, src->environment);
1535 fstrcpy( dst->driverpath, src->driverpath);
1536 fstrcpy( dst->datafile, src->datafile);
1537 fstrcpy( dst->configfile, src->configfile);
1538 fstrcpy( dst->helpfile, src->helpfile);
1539 fstrcpy( dst->monitorname, src->monitorname);
1540 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1541 dst->dependentfiles = src->dependentfiles;
1544 #if 0 /* Debugging function */
1546 static char* ffmt(unsigned char *c){
1548 static char ffmt_str[17];
1550 for (i=0; i<16; i++) {
1551 if ((c[i] < ' ') || (c[i] > '~'))
1562 /****************************************************************************
1563 ****************************************************************************/
1564 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1565 struct current_user *user, WERROR *perr)
1567 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1568 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1569 const char *architecture;
1574 connection_struct *conn;
1584 memset(inbuf, '\0', sizeof(inbuf));
1585 memset(outbuf, '\0', sizeof(outbuf));
1589 driver=driver_abstract.info_3;
1590 else if (level==6) {
1591 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1592 driver = &converted_driver;
1594 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1598 architecture = get_short_archi(driver->environment);
1601 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1602 * Note we must be root to do this.
1605 null_pw = data_blob(NULL, 0);
1606 fstrcpy(res_type, "A:");
1608 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1612 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1613 *perr = ntstatus_to_werror(nt_status);
1618 * Save who we are - we are temporarily becoming the connection user.
1621 if (!become_user(conn, conn->vuid)) {
1622 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1627 * make the directories version and version\driver_name
1628 * under the architecture directory.
1630 DEBUG(5,("Creating first directory\n"));
1631 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1632 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1633 mkdir_internal(conn, new_dir, bad_path);
1635 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1636 * listed for this driver which has already been moved, skip it (note:
1637 * drivers may list the same file name several times. Then check if the
1638 * file already exists in archi\cversion\, if so, check that the version
1639 * info (or time stamps if version info is unavailable) is newer (or the
1640 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1641 * Otherwise, delete the file.
1643 * If a file is not moved to archi\cversion\ because of an error, all the
1644 * rest of the 'unmoved' driver files are removed from archi\. If one or
1645 * more of the driver's files was already moved to archi\cversion\, it
1646 * potentially leaves the driver in a partially updated state. Version
1647 * trauma will most likely occur if an client attempts to use any printer
1648 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1649 * done is appropriate... later JRR
1652 DEBUG(5,("Moving files now !\n"));
1654 if (driver->driverpath && strlen(driver->driverpath)) {
1655 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1656 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1657 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1659 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1660 status = rename_internals(conn, new_name, old_name, 0, True);
1661 if (!NT_STATUS_IS_OK(status)) {
1662 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1663 new_name, old_name));
1664 *perr = ntstatus_to_werror(status);
1665 unlink_internals(conn, 0, new_name);
1669 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1670 unlink_internals(conn, 0, new_name);
1674 if (driver->datafile && strlen(driver->datafile)) {
1675 if (!strequal(driver->datafile, driver->driverpath)) {
1676 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1677 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1678 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1680 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1681 status = rename_internals(conn, new_name, old_name, 0, True);
1682 if (!NT_STATUS_IS_OK(status)) {
1683 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1684 new_name, old_name));
1685 *perr = ntstatus_to_werror(status);
1686 unlink_internals(conn, 0, new_name);
1690 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1691 unlink_internals(conn, 0, new_name);
1696 if (driver->configfile && strlen(driver->configfile)) {
1697 if (!strequal(driver->configfile, driver->driverpath) &&
1698 !strequal(driver->configfile, driver->datafile)) {
1699 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1700 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1701 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1703 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1704 status = rename_internals(conn, new_name, old_name, 0, True);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1707 new_name, old_name));
1708 *perr = ntstatus_to_werror(status);
1709 unlink_internals(conn, 0, new_name);
1713 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1714 unlink_internals(conn, 0, new_name);
1719 if (driver->helpfile && strlen(driver->helpfile)) {
1720 if (!strequal(driver->helpfile, driver->driverpath) &&
1721 !strequal(driver->helpfile, driver->datafile) &&
1722 !strequal(driver->helpfile, driver->configfile)) {
1723 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1724 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1725 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1727 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1728 status = rename_internals(conn, new_name, old_name, 0, True);
1729 if (!NT_STATUS_IS_OK(status)) {
1730 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1731 new_name, old_name));
1732 *perr = ntstatus_to_werror(status);
1733 unlink_internals(conn, 0, new_name);
1737 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1738 unlink_internals(conn, 0, new_name);
1743 if (driver->dependentfiles) {
1744 for (i=0; *driver->dependentfiles[i]; i++) {
1745 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1746 !strequal(driver->dependentfiles[i], driver->datafile) &&
1747 !strequal(driver->dependentfiles[i], driver->configfile) &&
1748 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1750 for (j=0; j < i; j++) {
1751 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1756 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1757 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1758 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1760 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1761 status = rename_internals(conn, new_name, old_name, 0, True);
1762 if (!NT_STATUS_IS_OK(status)) {
1763 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1764 new_name, old_name));
1765 *perr = ntstatus_to_werror(status);
1766 unlink_internals(conn, 0, new_name);
1770 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1771 unlink_internals(conn, 0, new_name);
1778 close_cnum(conn, user->vuid);
1781 return ver == -1 ? False : True;
1784 /****************************************************************************
1785 ****************************************************************************/
1786 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1789 const char *architecture;
1795 TDB_DATA kbuf, dbuf;
1797 architecture = get_short_archi(driver->environment);
1799 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1800 * \\server is added in the rpc server layer.
1801 * It does make sense to NOT store the server's name in the printer TDB.
1804 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1806 /* .inf files do not always list a file for each of the four standard files.
1807 * Don't prepend a path to a null filename, or client claims:
1808 * "The server on which the printer resides does not have a suitable
1809 * <printer driver name> printer driver installed. Click OK if you
1810 * wish to install the driver on your local machine."
1812 if (strlen(driver->driverpath)) {
1813 fstrcpy(temp_name, driver->driverpath);
1814 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1817 if (strlen(driver->datafile)) {
1818 fstrcpy(temp_name, driver->datafile);
1819 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1822 if (strlen(driver->configfile)) {
1823 fstrcpy(temp_name, driver->configfile);
1824 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1827 if (strlen(driver->helpfile)) {
1828 fstrcpy(temp_name, driver->helpfile);
1829 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1832 if (driver->dependentfiles) {
1833 for (i=0; *driver->dependentfiles[i]; i++) {
1834 fstrcpy(temp_name, driver->dependentfiles[i]);
1835 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1839 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1841 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1848 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1851 driver->environment,
1856 driver->monitorname,
1857 driver->defaultdatatype);
1859 if (driver->dependentfiles) {
1860 for (i=0; *driver->dependentfiles[i]; i++) {
1861 len += tdb_pack(buf+len, buflen-len, "f",
1862 driver->dependentfiles[i]);
1866 if (len != buflen) {
1869 tb = (char *)SMB_REALLOC(buf, len);
1871 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1882 kbuf.dsize = strlen(key)+1;
1886 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1890 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1896 /****************************************************************************
1897 ****************************************************************************/
1898 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1900 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1903 info3.cversion = driver->version;
1904 fstrcpy(info3.name,driver->name);
1905 fstrcpy(info3.environment,driver->environment);
1906 fstrcpy(info3.driverpath,driver->driverpath);
1907 fstrcpy(info3.datafile,driver->datafile);
1908 fstrcpy(info3.configfile,driver->configfile);
1909 fstrcpy(info3.helpfile,driver->helpfile);
1910 fstrcpy(info3.monitorname,driver->monitorname);
1911 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1912 info3.dependentfiles = driver->dependentfiles;
1914 return add_a_printer_driver_3(&info3);
1918 /****************************************************************************
1919 ****************************************************************************/
1920 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1922 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1926 fstrcpy(info.name, driver);
1927 fstrcpy(info.defaultdatatype, "RAW");
1929 fstrcpy(info.driverpath, "");
1930 fstrcpy(info.datafile, "");
1931 fstrcpy(info.configfile, "");
1932 fstrcpy(info.helpfile, "");
1934 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
1937 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1938 fstrcpy(info.dependentfiles[0], "");
1940 *info_ptr = memdup(&info, sizeof(info));
1945 /****************************************************************************
1946 ****************************************************************************/
1947 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1949 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1950 TDB_DATA kbuf, dbuf;
1951 const char *architecture;
1956 ZERO_STRUCT(driver);
1958 architecture = get_short_archi(arch);
1960 if ( !architecture )
1961 return WERR_UNKNOWN_PRINTER_DRIVER;
1963 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1965 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1968 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1970 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1973 kbuf.dsize = strlen(key)+1;
1975 dbuf = tdb_fetch(tdb_drivers, kbuf);
1977 return WERR_UNKNOWN_PRINTER_DRIVER;
1979 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1988 driver.defaultdatatype);
1991 while (len < dbuf.dsize) {
1994 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
1995 if (tddfs == NULL) {
1996 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1999 else driver.dependentfiles = tddfs;
2001 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2002 &driver.dependentfiles[i]);
2006 if (driver.dependentfiles != NULL)
2007 fstrcpy(driver.dependentfiles[i], "");
2009 SAFE_FREE(dbuf.dptr);
2011 if (len != dbuf.dsize) {
2012 SAFE_FREE(driver.dependentfiles);
2014 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2017 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2022 /****************************************************************************
2023 Debugging function, dump at level 6 the struct in the logs.
2024 ****************************************************************************/
2026 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2029 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2032 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2038 if (driver.info_3 == NULL)
2041 info3=driver.info_3;
2043 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2044 DEBUGADD(20,("name:[%s]\n", info3->name));
2045 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2046 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2047 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2048 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2049 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2050 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2051 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2053 for (i=0; info3->dependentfiles &&
2054 *info3->dependentfiles[i]; i++) {
2055 DEBUGADD(20,("dependentfile:[%s]\n",
2056 info3->dependentfiles[i]));
2063 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2071 /****************************************************************************
2072 ****************************************************************************/
2073 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2077 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2082 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2083 nt_devmode->devicename,
2084 nt_devmode->formname,
2086 nt_devmode->specversion,
2087 nt_devmode->driverversion,
2089 nt_devmode->driverextra,
2090 nt_devmode->orientation,
2091 nt_devmode->papersize,
2092 nt_devmode->paperlength,
2093 nt_devmode->paperwidth,
2096 nt_devmode->defaultsource,
2097 nt_devmode->printquality,
2100 nt_devmode->yresolution,
2101 nt_devmode->ttoption,
2102 nt_devmode->collate,
2103 nt_devmode->logpixels,
2106 nt_devmode->bitsperpel,
2107 nt_devmode->pelswidth,
2108 nt_devmode->pelsheight,
2109 nt_devmode->displayflags,
2110 nt_devmode->displayfrequency,
2111 nt_devmode->icmmethod,
2112 nt_devmode->icmintent,
2113 nt_devmode->mediatype,
2114 nt_devmode->dithertype,
2115 nt_devmode->reserved1,
2116 nt_devmode->reserved2,
2117 nt_devmode->panningwidth,
2118 nt_devmode->panningheight,
2119 nt_devmode->private);
2122 if (nt_devmode->private) {
2123 len += tdb_pack(buf+len, buflen-len, "B",
2124 nt_devmode->driverextra,
2125 nt_devmode->private);
2128 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2133 /****************************************************************************
2134 Pack all values in all printer keys
2135 ***************************************************************************/
2137 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2141 REGISTRY_VALUE *val;
2142 REGVAL_CTR *val_ctr;
2149 /* loop over all keys */
2151 for ( i=0; i<data->num_keys; i++ ) {
2152 val_ctr = &data->keys[i].values;
2153 num_values = regval_ctr_numvals( val_ctr );
2155 /* loop over all values */
2157 for ( j=0; j<num_values; j++ ) {
2158 /* pathname should be stored as <key>\<value> */
2160 val = regval_ctr_specific_value( val_ctr, j );
2161 pstrcpy( path, data->keys[i].name );
2162 pstrcat( path, "\\" );
2163 pstrcat( path, regval_name(val) );
2165 len += tdb_pack(buf+len, buflen-len, "pPdB",
2170 regval_data_p(val) );
2177 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2183 /****************************************************************************
2184 Delete a printer - this just deletes the printer info file, any open
2185 handles are not affected.
2186 ****************************************************************************/
2188 uint32 del_a_printer(const char *sharename)
2192 pstring printdb_path;
2194 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2196 kbuf.dsize=strlen(key)+1;
2197 tdb_delete(tdb_printers, kbuf);
2199 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2201 kbuf.dsize=strlen(key)+1;
2202 tdb_delete(tdb_printers, kbuf);
2204 close_all_print_db();
2206 if (geteuid() == 0) {
2207 pstrcpy(printdb_path, lock_path("printing/"));
2208 pstrcat(printdb_path, sharename);
2209 pstrcat(printdb_path, ".tdb");
2211 unlink(printdb_path);
2217 /****************************************************************************
2218 ****************************************************************************/
2219 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2225 TDB_DATA kbuf, dbuf;
2228 * in addprinter: no servername and the printer is the name
2229 * in setprinter: servername is \\server
2230 * and printer is \\server\\printer
2232 * Samba manages only local printers.
2233 * we currently don't support things like i
2234 * path=\\other_server\printer
2236 * We only store the printername, not \\server\printername
2239 if ( info->servername[0] != '\0' ) {
2240 trim_string(info->printername, info->servername, NULL);
2241 trim_char(info->printername, '\\', '\0');
2242 info->servername[0]='\0';
2246 * JFM: one day I'll forget.
2247 * below that's info->portname because that's the SAMBA sharename
2248 * and I made NT 'thinks' it's the portname
2249 * the info->sharename is the thing you can name when you add a printer
2250 * that's the short-name when you create shared printer for 95/98
2251 * So I've made a limitation in SAMBA: you can only have 1 printer model
2252 * behind a SAMBA share.
2260 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2263 info->default_priority,
2280 info->printprocessor,
2284 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2286 len += pack_values( &info->data, buf+len, buflen-len );
2288 if (buflen != len) {
2291 tb = (char *)SMB_REALLOC(buf, len);
2293 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2303 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2306 kbuf.dsize = strlen(key)+1;
2310 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2313 if (!W_ERROR_IS_OK(ret))
2314 DEBUG(8, ("error updating printer to tdb on disk\n"));
2318 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2319 info->sharename, info->drivername, info->portname, len));
2325 /****************************************************************************
2326 Malloc and return an NT devicemode.
2327 ****************************************************************************/
2329 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2332 char adevice[MAXDEVICENAME];
2333 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2335 if (nt_devmode == NULL) {
2336 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2340 ZERO_STRUCTP(nt_devmode);
2342 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2343 fstrcpy(nt_devmode->devicename, adevice);
2345 fstrcpy(nt_devmode->formname, "Letter");
2347 nt_devmode->specversion = 0x0401;
2348 nt_devmode->driverversion = 0x0400;
2349 nt_devmode->size = 0x00DC;
2350 nt_devmode->driverextra = 0x0000;
2351 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2352 DEFAULTSOURCE | COPIES | SCALE |
2353 PAPERSIZE | ORIENTATION;
2354 nt_devmode->orientation = 1;
2355 nt_devmode->papersize = PAPER_LETTER;
2356 nt_devmode->paperlength = 0;
2357 nt_devmode->paperwidth = 0;
2358 nt_devmode->scale = 0x64;
2359 nt_devmode->copies = 1;
2360 nt_devmode->defaultsource = BIN_FORMSOURCE;
2361 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2362 nt_devmode->color = COLOR_MONOCHROME;
2363 nt_devmode->duplex = DUP_SIMPLEX;
2364 nt_devmode->yresolution = 0;
2365 nt_devmode->ttoption = TT_SUBDEV;
2366 nt_devmode->collate = COLLATE_FALSE;
2367 nt_devmode->icmmethod = 0;
2368 nt_devmode->icmintent = 0;
2369 nt_devmode->mediatype = 0;
2370 nt_devmode->dithertype = 0;
2372 /* non utilisés par un driver d'imprimante */
2373 nt_devmode->logpixels = 0;
2374 nt_devmode->bitsperpel = 0;
2375 nt_devmode->pelswidth = 0;
2376 nt_devmode->pelsheight = 0;
2377 nt_devmode->displayflags = 0;
2378 nt_devmode->displayfrequency = 0;
2379 nt_devmode->reserved1 = 0;
2380 nt_devmode->reserved2 = 0;
2381 nt_devmode->panningwidth = 0;
2382 nt_devmode->panningheight = 0;
2384 nt_devmode->private = NULL;
2388 /****************************************************************************
2389 Deepcopy an NT devicemode.
2390 ****************************************************************************/
2392 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2394 NT_DEVICEMODE *new_nt_devicemode = NULL;
2396 if ( !nt_devicemode )
2399 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2400 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2404 new_nt_devicemode->private = NULL;
2405 if (nt_devicemode->private != NULL) {
2406 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2407 SAFE_FREE(new_nt_devicemode);
2408 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2413 return new_nt_devicemode;
2416 /****************************************************************************
2417 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2418 ****************************************************************************/
2420 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2422 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2424 if(nt_devmode == NULL)
2427 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2429 SAFE_FREE(nt_devmode->private);
2430 SAFE_FREE(*devmode_ptr);
2433 /****************************************************************************
2434 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2435 ****************************************************************************/
2436 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2438 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2439 NT_PRINTER_DATA *data;
2445 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2447 free_nt_devicemode(&info->devmode);
2449 /* clean up all registry keys */
2452 for ( i=0; i<data->num_keys; i++ ) {
2453 SAFE_FREE( data->keys[i].name );
2454 regval_ctr_destroy( &data->keys[i].values );
2456 SAFE_FREE( data->keys );
2458 /* finally the top level structure */
2460 SAFE_FREE( *info_ptr );
2464 /****************************************************************************
2465 ****************************************************************************/
2466 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2470 NT_DEVICEMODE devmode;
2472 ZERO_STRUCT(devmode);
2474 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2476 if (!*nt_devmode) return len;
2478 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2482 &devmode.specversion,
2483 &devmode.driverversion,
2485 &devmode.driverextra,
2486 &devmode.orientation,
2488 &devmode.paperlength,
2489 &devmode.paperwidth,
2492 &devmode.defaultsource,
2493 &devmode.printquality,
2496 &devmode.yresolution,
2502 &devmode.bitsperpel,
2504 &devmode.pelsheight,
2505 &devmode.displayflags,
2506 &devmode.displayfrequency,
2510 &devmode.dithertype,
2513 &devmode.panningwidth,
2514 &devmode.panningheight,
2517 if (devmode.private) {
2518 /* the len in tdb_unpack is an int value and
2519 * devmode.driverextra is only a short
2521 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2522 devmode.driverextra=(uint16)extra_len;
2524 /* check to catch an invalid TDB entry so we don't segfault */
2525 if (devmode.driverextra == 0) {
2526 devmode.private = NULL;
2530 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2532 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2533 if (devmode.private)
2534 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2539 /****************************************************************************
2540 Allocate and initialize a new slot.
2541 ***************************************************************************/
2543 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2548 if ( !data || !name )
2551 /* allocate another slot in the NT_PRINTER_KEY array */
2553 d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1);
2557 key_index = data->num_keys;
2559 /* initialze new key */
2562 data->keys[key_index].name = SMB_STRDUP( name );
2564 ZERO_STRUCTP( &data->keys[key_index].values );
2566 regval_ctr_init( &data->keys[key_index].values );
2568 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2573 /****************************************************************************
2574 search for a registry key name in the existing printer data
2575 ***************************************************************************/
2577 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2582 if ( !data || !name )
2585 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2587 /* loop over all existing keys */
2589 for ( i=0; i<data->num_keys; i++ ) {
2590 if ( strequal(data->keys[i].name, name) ) {
2591 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2601 /****************************************************************************
2602 ***************************************************************************/
2604 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2608 int num_subkeys = 0;
2610 fstring *ptr, *subkeys_ptr = NULL;
2616 for ( i=0; i<data->num_keys; i++ ) {
2617 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2618 /* match sure it is a subkey and not the key itself */
2620 key_len = strlen( key );
2621 if ( strlen(data->keys[i].name) == key_len )
2624 /* get subkey path */
2626 p = data->keys[i].name + key_len;
2629 fstrcpy( subkeyname, p );
2630 if ( (p = strchr( subkeyname, '\\' )) )
2633 /* don't add a key more than once */
2635 for ( j=0; j<num_subkeys; j++ ) {
2636 if ( strequal( subkeys_ptr[j], subkeyname ) )
2640 if ( j != num_subkeys )
2643 /* found a match, so allocate space and copy the name */
2645 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2646 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2648 SAFE_FREE( subkeys );
2653 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2659 /* tag of the end */
2662 fstrcpy(subkeys_ptr[num_subkeys], "" );
2664 *subkeys = subkeys_ptr;
2670 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2673 smb_ucs2_t conv_str[1024];
2676 regval_ctr_delvalue(ctr, val_name);
2677 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2678 STR_TERMINATE | STR_NOALIGN);
2679 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2680 (char *) conv_str, str_size);
2683 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2686 regval_ctr_delvalue(ctr, val_name);
2687 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2688 (char *) &dword, sizeof(dword));
2691 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2694 uint8 bin_bool = (b ? 1 : 0);
2695 regval_ctr_delvalue(ctr, val_name);
2696 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2697 (char *) &bin_bool, sizeof(bin_bool));
2700 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2701 const char *multi_sz)
2703 smb_ucs2_t *conv_strs = NULL;
2706 /* a multi-sz has to have a null string terminator, i.e., the last
2707 string must be followed by two nulls */
2708 str_size = strlen(multi_sz) + 2;
2709 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2714 /* Change to byte units. */
2715 str_size *= sizeof(smb_ucs2_t);
2716 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2717 STR_TERMINATE | STR_NOALIGN);
2719 regval_ctr_delvalue(ctr, val_name);
2720 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2721 (char *) conv_strs, str_size);
2722 safe_free(conv_strs);
2726 /****************************************************************************
2727 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2729 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2730 * @return BOOL indicating success or failure
2731 ***************************************************************************/
2733 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2735 REGVAL_CTR *ctr = NULL;
2738 char *allocated_string = NULL;
2739 const char *ascii_str;
2742 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2743 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2744 ctr = &info2->data.keys[i].values;
2746 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2747 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2749 /* we make the assumption that the netbios name is the same
2750 as the DNS name sinc ethe former will be what we used to
2753 if ( get_mydnsdomname( dnssuffix ) )
2754 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2756 fstrcpy( longname, global_myname() );
2758 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2760 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2761 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2762 SAFE_FREE(allocated_string);
2764 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2765 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2766 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2767 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2768 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2769 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2770 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2771 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2772 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2774 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2775 (info2->attributes &
2776 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2778 switch (info2->attributes & 0x3) {
2780 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2783 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2786 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2789 ascii_str = "unknown";
2791 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2796 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2800 REGVAL_CTR *ctr=NULL;
2802 /* find the DsSpooler key */
2803 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2804 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2805 ctr = &info2->data.keys[i].values;
2807 regval_ctr_delvalue(ctr, "objectGUID");
2808 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2809 (char *) &guid, sizeof(struct uuid));
2812 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2813 NT_PRINTER_INFO_LEVEL *printer)
2817 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2818 char *srv_dn_utf8, **srv_cn_utf8;
2821 const char *attrs[] = {"objectGUID", NULL};
2823 WERROR win_rc = WERR_OK;
2825 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2827 /* figure out where to publish */
2828 ads_find_machine_acct(ads, &res, global_myname());
2830 /* We use ldap_get_dn here as we need the answer
2831 * in utf8 to call ldap_explode_dn(). JRA. */
2833 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2836 return WERR_SERVER_UNAVAILABLE;
2838 ads_msgfree(ads, res);
2839 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2841 ldap_memfree(srv_dn_utf8);
2843 return WERR_SERVER_UNAVAILABLE;
2845 /* Now convert to CH_UNIX. */
2846 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2847 ldap_memfree(srv_dn_utf8);
2848 ldap_memfree(srv_cn_utf8);
2850 return WERR_SERVER_UNAVAILABLE;
2852 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2853 ldap_memfree(srv_dn_utf8);
2854 ldap_memfree(srv_cn_utf8);
2857 return WERR_SERVER_UNAVAILABLE;
2860 ldap_memfree(srv_dn_utf8);
2861 ldap_memfree(srv_cn_utf8);
2863 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2864 printer->info_2->sharename, srv_dn);
2867 SAFE_FREE(srv_cn_0);
2869 /* build the ads mods */
2870 ctx = talloc_init("nt_printer_publish_ads");
2871 mods = ads_init_mods(ctx);
2873 get_local_printer_publishing_data(ctx, &mods,
2874 &printer->info_2->data);
2875 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2876 printer->info_2->sharename);
2879 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2880 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2881 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2883 if (!ADS_ERR_OK(ads_rc))
2884 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2886 talloc_destroy(ctx);
2888 /* retreive the guid and store it locally */
2889 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2891 ads_pull_guid(ads, res, &guid);
2892 ads_msgfree(ads, res);
2893 store_printer_guid(printer->info_2, guid);
2894 win_rc = mod_a_printer(printer, 2);
2901 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2902 NT_PRINTER_INFO_LEVEL *printer)
2906 char *prt_dn = NULL;
2908 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2910 /* remove the printer from the directory */
2911 ads_rc = ads_find_printer_on_server(ads, &res,
2912 printer->info_2->sharename, global_myname());
2914 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2915 prt_dn = ads_get_dn(ads, res);
2916 ads_rc = ads_del_dn(ads, prt_dn);
2917 ads_memfree(ads, prt_dn);
2920 ads_msgfree(ads, res);
2924 /****************************************************************************
2925 * Publish a printer in the directory
2927 * @param snum describing printer service
2928 * @return WERROR indicating status of publishing
2929 ***************************************************************************/
2931 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2934 ADS_STRUCT *ads = NULL;
2935 NT_PRINTER_INFO_LEVEL *printer = NULL;
2938 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2939 if (!W_ERROR_IS_OK(win_rc))
2943 case SPOOL_DS_PUBLISH:
2944 case SPOOL_DS_UPDATE:
2945 /* set the DsSpooler info and attributes */
2946 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2947 win_rc = WERR_NOMEM;
2951 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2953 case SPOOL_DS_UNPUBLISH:
2954 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2957 win_rc = WERR_NOT_SUPPORTED;
2961 win_rc = mod_a_printer(printer, 2);
2962 if (!W_ERROR_IS_OK(win_rc)) {
2963 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2967 ads = ads_init(NULL, NULL, NULL);
2969 DEBUG(3, ("ads_init() failed\n"));
2970 win_rc = WERR_SERVER_UNAVAILABLE;
2973 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2974 SAFE_FREE(ads->auth.password);
2975 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2978 /* ads_connect() will find the DC for us */
2979 ads_rc = ads_connect(ads);
2980 if (!ADS_ERR_OK(ads_rc)) {
2981 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2982 win_rc = WERR_ACCESS_DENIED;
2987 case SPOOL_DS_PUBLISH:
2988 case SPOOL_DS_UPDATE:
2989 win_rc = nt_printer_publish_ads(ads, printer);
2991 case SPOOL_DS_UNPUBLISH:
2992 win_rc = nt_printer_unpublish_ads(ads, printer);
2997 free_a_printer(&printer, 2);
3002 WERROR check_published_printers(void)
3005 ADS_STRUCT *ads = NULL;
3007 int n_services = lp_numservices();
3008 NT_PRINTER_INFO_LEVEL *printer = NULL;
3010 ads = ads_init(NULL, NULL, NULL);
3012 DEBUG(3, ("ads_init() failed\n"));
3013 return WERR_SERVER_UNAVAILABLE;
3015 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3016 SAFE_FREE(ads->auth.password);
3017 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3020 /* ads_connect() will find the DC for us */
3021 ads_rc = ads_connect(ads);
3022 if (!ADS_ERR_OK(ads_rc)) {
3023 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3025 return WERR_ACCESS_DENIED;
3028 for (snum = 0; snum < n_services; snum++) {
3029 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3032 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3033 lp_servicename(snum))) &&
3034 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3035 nt_printer_publish_ads(ads, printer);
3037 free_a_printer(&printer, 2);
3044 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3047 NT_PRINTER_INFO_LEVEL *printer = NULL;
3049 REGISTRY_VALUE *guid_val;
3053 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3055 if (!W_ERROR_IS_OK(win_rc) ||
3056 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3057 ((i = lookup_printerkey(&printer->info_2->data,
3058 SPOOL_DSSPOOLER_KEY)) < 0) ||
3059 !(ctr = &printer->info_2->data.keys[i].values) ||
3060 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3061 free_a_printer(&printer, 2);
3065 /* fetching printer guids really ought to be a separate function.. */
3066 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3067 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3069 free_a_printer(&printer, 2);
3073 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3078 WERROR check_published_printers(void)
3083 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3088 #endif /* HAVE_ADS */
3090 /****************************************************************************
3091 ***************************************************************************/
3093 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3095 NT_PRINTER_DATA *data;
3097 int removed_keys = 0;
3101 empty_slot = data->num_keys;
3104 return WERR_INVALID_PARAM;
3106 /* remove all keys */
3108 if ( !strlen(key) ) {
3109 for ( i=0; i<data->num_keys; i++ ) {
3110 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3111 data->keys[i].name));
3113 SAFE_FREE( data->keys[i].name );
3114 regval_ctr_destroy( &data->keys[i].values );
3117 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3120 SAFE_FREE( data->keys );
3121 ZERO_STRUCTP( data );
3126 /* remove a specific key (and all subkeys) */
3128 for ( i=0; i<data->num_keys; i++ ) {
3129 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3130 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3131 data->keys[i].name));
3133 SAFE_FREE( data->keys[i].name );
3134 regval_ctr_destroy( &data->keys[i].values );
3136 /* mark the slot as empty */
3138 ZERO_STRUCTP( &data->keys[i] );
3142 /* find the first empty slot */
3144 for ( i=0; i<data->num_keys; i++ ) {
3145 if ( !data->keys[i].name ) {
3152 if ( i == data->num_keys )
3153 /* nothing was removed */
3154 return WERR_INVALID_PARAM;
3156 /* move everything down */
3158 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3159 if ( data->keys[i].name ) {
3160 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3161 ZERO_STRUCTP( &data->keys[i] );
3169 data->num_keys -= removed_keys;
3171 /* sanity check to see if anything is left */
3173 if ( !data->num_keys ) {
3174 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3176 SAFE_FREE( data->keys );
3177 ZERO_STRUCTP( data );
3183 /****************************************************************************
3184 ***************************************************************************/
3186 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3188 WERROR result = WERR_OK;
3191 /* we must have names on non-zero length */
3193 if ( !key || !*key|| !value || !*value )
3194 return WERR_INVALID_NAME;
3196 /* find the printer key first */
3198 key_index = lookup_printerkey( &p2->data, key );
3199 if ( key_index == -1 )
3202 /* make sure the value exists so we can return the correct error code */
3204 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3205 return WERR_BADFILE;
3207 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3209 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3215 /****************************************************************************
3216 ***************************************************************************/
3218 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3219 uint32 type, uint8 *data, int real_len )
3221 WERROR result = WERR_OK;
3224 /* we must have names on non-zero length */
3226 if ( !key || !*key|| !value || !*value )
3227 return WERR_INVALID_NAME;
3229 /* find the printer key first */
3231 key_index = lookup_printerkey( &p2->data, key );
3232 if ( key_index == -1 )
3233 key_index = add_new_printer_key( &p2->data, key );
3235 if ( key_index == -1 )
3238 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3239 type, (const char *)data, real_len );
3241 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3242 key, value, type, real_len ));
3247 /****************************************************************************
3248 ***************************************************************************/
3250 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3254 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3257 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3260 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3263 /****************************************************************************
3264 Unpack a list of registry values frem the TDB
3265 ***************************************************************************/
3267 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3271 pstring string, valuename, keyname;
3275 REGISTRY_VALUE *regval_p;
3278 /* add the "PrinterDriverData" key first for performance reasons */
3280 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3282 /* loop and unpack the rest of the registry values */
3286 /* check to see if there are any more registry values */
3289 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3293 /* unpack the next regval */
3295 len += tdb_unpack(buf+len, buflen-len, "fdB",
3302 * break of the keyname from the value name.
3303 * Valuenames can have embedded '\'s so be careful.
3304 * only support one level of keys. See the
3305 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3309 str = strchr_m( string, '\\');
3311 /* Put in "PrinterDriverData" is no key specified */
3314 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3315 pstrcpy( valuename, string );
3319 pstrcpy( keyname, string );
3320 pstrcpy( valuename, str+1 );
3323 /* see if we need a new key */
3325 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3326 key_index = add_new_printer_key( printer_data, keyname );
3328 if ( key_index == -1 ) {
3329 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3334 /* add the new value */
3336 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3338 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3340 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3346 /****************************************************************************
3347 ***************************************************************************/
3349 static void map_to_os2_driver(fstring drivername)
3351 static BOOL initialised=False;
3352 static fstring last_from,last_to;
3353 char *mapfile = lp_os2_driver_map();
3354 char **lines = NULL;
3358 if (!strlen(drivername))
3365 *last_from = *last_to = 0;
3369 if (strequal(drivername,last_from)) {
3370 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3371 fstrcpy(drivername,last_to);
3375 lines = file_lines_load(mapfile, &numlines);
3376 if (numlines == 0) {
3377 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3381 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3383 for( i = 0; i < numlines; i++) {
3384 char *nt_name = lines[i];
3385 char *os2_name = strchr(nt_name,'=');
3392 while (isspace(*nt_name))
3395 if (!*nt_name || strchr("#;",*nt_name))
3399 int l = strlen(nt_name);
3400 while (l && isspace(nt_name[l-1])) {
3406 while (isspace(*os2_name))
3410 int l = strlen(os2_name);
3411 while (l && isspace(os2_name[l-1])) {
3417 if (strequal(nt_name,drivername)) {
3418 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3419 fstrcpy(last_from,drivername);
3420 fstrcpy(last_to,os2_name);
3421 fstrcpy(drivername,os2_name);
3422 file_lines_free(lines);
3427 file_lines_free(lines);
3430 /****************************************************************************
3431 Get a default printer info 2 struct.
3432 ****************************************************************************/
3433 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3436 NT_PRINTER_INFO_LEVEL_2 info;
3440 snum = lp_servicenumber(sharename);
3442 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3443 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3444 servername, sharename);
3445 fstrcpy(info.sharename, sharename);
3446 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3448 /* by setting the driver name to an empty string, a local NT admin
3449 can now run the **local** APW to install a local printer driver
3450 for a Samba shared printer in 2.2. Without this, drivers **must** be
3451 installed on the Samba server for NT clients --jerry */
3452 #if 0 /* JERRY --do not uncomment-- */
3453 if (!*info.drivername)
3454 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3458 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3460 pstrcpy(info.comment, "");
3461 fstrcpy(info.printprocessor, "winprint");
3462 fstrcpy(info.datatype, "RAW");
3464 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3466 info.starttime = 0; /* Minutes since 12:00am GMT */
3467 info.untiltime = 0; /* Minutes since 12:00am GMT */
3469 info.default_priority = 1;
3470 info.setuptime = (uint32)time(NULL);
3473 * I changed this as I think it is better to have a generic
3474 * DEVMODE than to crash Win2k explorer.exe --jerry
3475 * See the HP Deskjet 990c Win2k drivers for an example.
3477 * However the default devmode appears to cause problems
3478 * with the HP CLJ 8500 PCL driver. Hence the addition of
3479 * the "default devmode" parameter --jerry 22/01/2002
3482 if (lp_default_devmode(snum)) {
3483 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3487 info.devmode = NULL;
3490 /* This will get the current RPC talloc context, but we should be
3491 passing this as a parameter... fixme... JRA ! */
3493 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3496 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3498 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3506 free_nt_devicemode(&info.devmode);
3507 return WERR_ACCESS_DENIED;
3510 /****************************************************************************
3511 ****************************************************************************/
3512 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3515 NT_PRINTER_INFO_LEVEL_2 info;
3517 int snum = lp_servicenumber(sharename);
3518 TDB_DATA kbuf, dbuf;
3519 fstring printername;
3520 char adevice[MAXDEVICENAME];
3524 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3527 kbuf.dsize = strlen(key)+1;
3529 dbuf = tdb_fetch(tdb_printers, kbuf);
3531 return get_a_printer_2_default(info_ptr, servername, sharename);
3533 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3536 &info.default_priority,
3553 info.printprocessor,
3557 /* Samba has to have shared raw drivers. */
3558 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3559 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3561 /* Restore the stripped strings. */
3562 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3564 if ( lp_force_printername(snum) )
3565 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3567 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3569 fstrcpy(info.printername, printername);
3571 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3574 * Some client drivers freak out if there is a NULL devmode
3575 * (probably the driver is not checking before accessing
3576 * the devmode pointer) --jerry
3578 * See comments in get_a_printer_2_default()
3581 if (lp_default_devmode(snum) && !info.devmode) {
3582 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3584 info.devmode = construct_nt_devicemode(printername);
3587 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3589 fstrcpy(info.devmode->devicename, adevice);
3592 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3594 /* This will get the current RPC talloc context, but we should be
3595 passing this as a parameter... fixme... JRA ! */
3597 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3599 /* Fix for OS/2 drivers. */
3601 if (get_remote_arch() == RA_OS2)
3602 map_to_os2_driver(info.drivername);
3604 SAFE_FREE(dbuf.dptr);
3605 *info_ptr=memdup(&info, sizeof(info));
3607 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3608 sharename, info.printername, info.drivername));
3613 /****************************************************************************
3614 Debugging function, dump at level 6 the struct in the logs.
3615 ****************************************************************************/
3616 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3619 NT_PRINTER_INFO_LEVEL_2 *info2;
3621 DEBUG(106,("Dumping printer at level [%d]\n", level));
3626 if (printer->info_2 == NULL)
3630 info2=printer->info_2;
3632 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3633 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3634 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3635 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3636 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3637 DEBUGADD(106,("status:[%d]\n", info2->status));
3638 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3639 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3640 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3641 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3642 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3644 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3645 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3646 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3647 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3648 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3649 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3650 DEBUGADD(106,("location:[%s]\n", info2->location));
3651 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3652 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3653 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3654 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3660 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3668 /****************************************************************************
3669 Update the changeid time.
3670 This is SO NASTY as some drivers need this to change, others need it
3671 static. This value will change every second, and I must hope that this
3672 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3674 ****************************************************************************/
3676 static uint32 rev_changeid(void)
3680 get_process_uptime(&tv);
3683 /* Return changeid as msec since spooler restart */
3684 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3687 * This setting seems to work well but is too untested
3688 * to replace the above calculation. Left in for experiementation
3689 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3691 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3695 /********************************************************************
3696 Send a message to all smbds about the printer that just changed
3697 ********************************************************************/
3699 static BOOL send_printer_mod_msg( char* printername )
3701 int len = strlen(printername);
3706 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3709 /* spam everyone that we just changed this printer */
3711 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3717 * The function below are the high level ones.
3718 * only those ones must be called from the spoolss code.
3722 /****************************************************************************
3723 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3724 ****************************************************************************/
3726 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3730 dump_a_printer(printer, level);
3733 * invalidate cache for all open handles to this printer.
3734 * cache for a given handle will be updated on the next
3738 invalidate_printer_hnd_cache( printer->info_2->sharename );
3739 send_printer_mod_msg( printer->info_2->sharename );
3745 * Update the changestamp. Emperical tests show that the
3746 * ChangeID is always updated,but c_setprinter is
3747 * global spooler variable (not per printer).
3750 /* ChangeID **must** be increasing over the lifetime
3751 of client's spoolss service in order for the
3752 client's cache to show updates */
3754 printer->info_2->changeid = rev_changeid();
3757 * Because one day someone will ask:
3758 * NT->NT An admin connection to a remote
3759 * printer show changes imeediately in
3760 * the properities dialog
3762 * A non-admin connection will only show the
3763 * changes after viewing the properites page
3764 * 2 times. Seems to be related to a
3765 * race condition in the client between the spooler
3766 * updating the local cache and the Explorer.exe GUI
3767 * actually displaying the properties.
3769 * This is fixed in Win2k. admin/non-admin
3770 * connections both display changes immediately.
3775 result=update_a_printer_2(printer->info_2);
3780 result=WERR_UNKNOWN_LEVEL;
3787 /****************************************************************************
3788 Initialize printer devmode & data with previously saved driver init values.
3789 ****************************************************************************/
3791 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3795 TDB_DATA kbuf, dbuf;
3796 NT_PRINTER_INFO_LEVEL_2 info;
3802 * Delete any printer data 'values' already set. When called for driver
3803 * replace, there will generally be some, but during an add printer, there
3804 * should not be any (if there are delete them).
3807 delete_all_printer_data( info_ptr, "" );
3809 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3812 kbuf.dsize = strlen(key)+1;
3814 dbuf = tdb_fetch(tdb_drivers, kbuf);
3817 * When changing to a driver that has no init info in the tdb, remove
3818 * the previous drivers init info and leave the new on blank.
3820 free_nt_devicemode(&info_ptr->devmode);
3825 * Get the saved DEVMODE..
3828 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3831 * The saved DEVMODE contains the devicename from the printer used during
3832 * the initialization save. Change it to reflect the new printer.
3835 if ( info.devmode ) {
3836 ZERO_STRUCT(info.devmode->devicename);
3837 fstrcpy(info.devmode->devicename, info_ptr->printername);
3841 * NT/2k does not change out the entire DeviceMode of a printer
3842 * when changing the driver. Only the driverextra, private, &
3843 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3845 * Later examination revealed that Windows NT/2k does reset the
3846 * the printer's device mode, bit **only** when you change a
3847 * property of the device mode such as the page orientation.
3852 /* Bind the saved DEVMODE to the new the printer */
3854 free_nt_devicemode(&info_ptr->devmode);
3855 info_ptr->devmode = info.devmode;
3857 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3858 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3860 /* Add the printer data 'values' to the new printer */
3862 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3865 SAFE_FREE(dbuf.dptr);
3870 /****************************************************************************
3871 Initialize printer devmode & data with previously saved driver init values.
3872 When a printer is created using AddPrinter, the drivername bound to the
3873 printer is used to lookup previously saved driver initialization info, which
3874 is bound to the new printer.
3875 ****************************************************************************/
3877 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3879 BOOL result = False;
3883 result = set_driver_init_2(printer->info_2);
3887 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3895 /****************************************************************************
3896 Delete driver init data stored for a specified driver
3897 ****************************************************************************/
3899 BOOL del_driver_init(char *drivername)
3904 if (!drivername || !*drivername) {
3905 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3909 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3912 kbuf.dsize = strlen(key)+1;
3914 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3916 return (tdb_delete(tdb_drivers, kbuf) == 0);
3919 /****************************************************************************
3920 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3921 in the tdb. Note: this is different from the driver entry and the printer
3922 entry. There should be a single driver init entry for each driver regardless
3923 of whether it was installed from NT or 2K. Technically, they should be
3924 different, but they work out to the same struct.
3925 ****************************************************************************/
3927 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3931 int buflen, len, ret;
3932 TDB_DATA kbuf, dbuf;
3939 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3941 len += pack_values( &info->data, buf+len, buflen-len );
3946 tb = (char *)SMB_REALLOC(buf, len);
3948 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3958 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3961 kbuf.dsize = strlen(key)+1;
3965 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3969 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3973 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3974 info->sharename, info->drivername));
3979 /****************************************************************************
3980 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3981 ****************************************************************************/
3983 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3987 dump_a_printer(printer, level);
3991 result = update_driver_init_2(printer->info_2);
4001 /****************************************************************************
4002 Convert the printer data value, a REG_BINARY array, into an initialization
4003 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4004 got to keep the endians happy :).
4005 ****************************************************************************/
4007 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4009 BOOL result = False;
4013 ZERO_STRUCT(devmode);
4015 prs_init(&ps, 0, ctx, UNMARSHALL);
4016 ps.data_p = (char *)data;
4017 ps.buffer_size = data_len;
4019 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4020 result = convert_devicemode("", &devmode, &nt_devmode);
4022 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4027 /****************************************************************************
4028 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4030 1. Use the driver's config DLL to this UNC printername and:
4031 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4032 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4033 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4035 The last step triggers saving the "driver initialization" information for
4036 this printer into the tdb. Later, new printers that use this driver will
4037 have this initialization information bound to them. This simulates the
4038 driver initialization, as if it had run on the Samba server (as it would
4041 The Win32 client side code requirement sucks! But until we can run arbitrary
4042 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4044 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4045 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4046 about it and you will realize why. JRR 010720
4047 ****************************************************************************/
4049 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4051 WERROR status = WERR_OK;
4052 TALLOC_CTX *ctx = NULL;
4053 NT_DEVICEMODE *nt_devmode = NULL;
4054 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4057 * When the DEVMODE is already set on the printer, don't try to unpack it.
4059 DEBUG(8,("save_driver_init_2: Enter...\n"));
4061 if ( !printer->info_2->devmode && data_len ) {
4063 * Set devmode on printer info, so entire printer initialization can be
4067 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4070 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4071 status = WERR_NOMEM;
4075 ZERO_STRUCTP(nt_devmode);
4078 * The DEVMODE is held in the 'data' component of the param in raw binary.
4079 * Convert it to to a devmode structure
4081 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4082 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4083 status = WERR_INVALID_PARAM;
4087 printer->info_2->devmode = nt_devmode;
4091 * Pack up and add (or update) the DEVMODE and any current printer data to
4092 * a 'driver init' element in the tdb
4096 if ( update_driver_init(printer, 2) != 0 ) {
4097 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4098 status = WERR_NOMEM;
4103 * If driver initialization info was successfully saved, set the current
4104 * printer to match it. This allows initialization of the current printer
4105 * as well as the driver.
4107 status = mod_a_printer(printer, 2);
4108 if (!W_ERROR_IS_OK(status)) {
4109 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4110 printer->info_2->printername));
4114 talloc_destroy(ctx);
4115 free_nt_devicemode( &nt_devmode );
4117 printer->info_2->devmode = tmp_devmode;
4122 /****************************************************************************
4123 Update the driver init info (DEVMODE and specifics) for a printer
4124 ****************************************************************************/
4126 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4128 WERROR status = WERR_OK;
4132 status = save_driver_init_2( printer, data, data_len );
4135 status = WERR_UNKNOWN_LEVEL;
4142 /****************************************************************************
4143 Deep copy a NT_PRINTER_DATA
4144 ****************************************************************************/
4146 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4148 int i, j, num_vals, new_key_index;
4149 REGVAL_CTR *src_key, *dst_key;
4152 return NT_STATUS_NO_MEMORY;
4154 for ( i=0; i<src->num_keys; i++ ) {
4156 /* create a new instance of the printerkey in the destination
4157 printer_data object */
4159 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4160 dst_key = &dst->keys[new_key_index].values;
4162 src_key = &src->keys[i].values;
4163 num_vals = regval_ctr_numvals( src_key );
4165 /* dup the printer entire printer key */
4167 for ( j=0; j<num_vals; j++ ) {
4168 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4172 return NT_STATUS_OK;
4175 /****************************************************************************
4176 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4178 ****************************************************************************/
4180 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4182 NT_PRINTER_INFO_LEVEL_2 *copy;
4187 if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4190 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4192 /* malloc()'d members copied here */
4194 copy->devmode = dup_nt_devicemode( printer->devmode );
4196 ZERO_STRUCT( copy->data );
4197 copy_printer_data( ©->data, &printer->data );
4199 /* this is talloc()'d; very ugly that we have a structure that
4200 is half malloc()'d and half talloc()'d but that is the way
4201 that the PRINTER_INFO stuff is written right now. --jerry */
4203 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4208 /****************************************************************************
4209 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4211 Previously the code had a memory allocation problem because it always
4212 used the TALLOC_CTX from the Printer_entry*. This context lasts
4213 as a long as the original handle is open. So if the client made a lot
4214 of getprinter[data]() calls, the memory usage would climb. Now we use
4215 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4216 still use the Printer_entry->ctx for maintaining the cache copy though
4217 since that object must live as long as the handle by definition.
4220 ****************************************************************************/
4222 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4223 const char *sharename)
4226 NT_PRINTER_INFO_LEVEL *printer = NULL;
4231 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4235 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4236 DEBUG(0,("get_a_printer: malloc fail.\n"));
4239 ZERO_STRUCTP(printer);
4242 fstrcpy( servername, print_hnd->servername );
4244 fstrcpy( servername, "%L" );
4245 standard_sub_basic( "", servername, sizeof(servername)-1 );
4249 * check for cache first. A Printer handle cannot changed
4250 * to another printer object so we only check that the printer
4251 * is actually for a printer and that the printer_info pointer
4255 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4256 && print_hnd->printer_info )
4258 /* get_talloc_ctx() works here because we need a short
4259 lived talloc context */
4261 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4263 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4269 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4271 *pp_printer = printer;
4277 /* no cache for this handle; see if we can match one from another handle.
4278 Make sure to use a short lived talloc ctx */
4281 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4283 /* fail to disk if we don't have it with any open handle */
4285 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4286 result = get_a_printer_2(&printer->info_2, servername, sharename );
4288 /* we have a new printer now. Save it with this handle */
4290 if ( W_ERROR_IS_OK(result) ) {
4291 dump_a_printer(printer, level);
4293 /* save a copy in cache */
4294 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4295 if ( !print_hnd->printer_info )
4296 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4298 if ( print_hnd->printer_info ) {
4299 /* make sure to use the handle's talloc ctx here since
4300 the printer_2 object must last until the handle is closed */
4302 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4304 /* don't fail the lookup just because the cache update failed */
4305 if ( !print_hnd->printer_info->info_2 )
4306 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4309 *pp_printer = printer;
4317 result=WERR_UNKNOWN_LEVEL;
4321 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4326 /****************************************************************************
4327 Deletes a NT_PRINTER_INFO_LEVEL struct.
4328 ****************************************************************************/
4330 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4333 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4335 DEBUG(104,("freeing a printer at level [%d]\n", level));
4337 if (printer == NULL)
4342 if (printer->info_2 != NULL) {
4343 free_nt_printer_info_level_2(&printer->info_2);
4354 SAFE_FREE(*pp_printer);
4358 /****************************************************************************
4359 ****************************************************************************/
4360 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4363 DEBUG(104,("adding a printer at level [%d]\n", level));
4364 dump_a_printer_driver(driver, level);
4368 result=add_a_printer_driver_3(driver.info_3);
4372 result=add_a_printer_driver_6(driver.info_6);
4382 /****************************************************************************
4383 ****************************************************************************/
4385 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4386 fstring drivername, const char *architecture, uint32 version)
4392 /* Sometime we just want any version of the driver */
4394 if ( version == DRIVER_ANY_VERSION ) {
4395 /* look for Win2k first and then for NT4 */
4396 result = get_a_printer_driver_3(&driver->info_3, drivername,
4399 if ( !W_ERROR_IS_OK(result) ) {
4400 result = get_a_printer_driver_3( &driver->info_3,
4401 drivername, architecture, 2 );
4404 result = get_a_printer_driver_3(&driver->info_3, drivername,
4405 architecture, version);
4414 if (W_ERROR_IS_OK(result))
4415 dump_a_printer_driver(*driver, level);
4420 /****************************************************************************
4421 ****************************************************************************/
4422 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4429 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4430 if (driver.info_3 != NULL)
4432 info3=driver.info_3;
4433 SAFE_FREE(info3->dependentfiles);
4434 ZERO_STRUCTP(info3);
4444 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4445 if (driver.info_6 != NULL) {
4446 info6=driver.info_6;
4447 SAFE_FREE(info6->dependentfiles);
4448 SAFE_FREE(info6->previousnames);
4449 ZERO_STRUCTP(info6);
4465 /****************************************************************************
4466 Determine whether or not a particular driver is currently assigned
4468 ****************************************************************************/
4470 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4473 int n_services = lp_numservices();
4474 NT_PRINTER_INFO_LEVEL *printer = NULL;
4475 BOOL in_use = False;
4480 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4482 /* loop through the printers.tdb and check for the drivername */
4484 for (snum=0; snum<n_services && !in_use; snum++) {
4485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4488 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4491 if ( strequal(info_3->name, printer->info_2->drivername) )
4494 free_a_printer( &printer, 2 );
4497 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4500 NT_PRINTER_DRIVER_INFO_LEVEL d;
4503 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4505 /* we can still remove the driver if there is one of
4506 "Windows NT x86" version 2 or 3 left */
4508 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4509 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4512 switch ( info_3->cversion ) {
4514 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4517 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4520 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4522 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4527 /* now check the error code */
4529 if ( W_ERROR_IS_OK(werr) ) {
4530 /* it's ok to remove the driver, we have other architctures left */
4532 free_a_printer_driver( d, 3 );
4536 /* report that the driver is not in use by default */
4542 /**********************************************************************
4543 Check to see if a ogiven file is in use by *info
4544 *********************************************************************/
4546 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4553 if ( strequal(file, info->driverpath) )
4556 if ( strequal(file, info->datafile) )
4559 if ( strequal(file, info->configfile) )
4562 if ( strequal(file, info->helpfile) )
4565 /* see of there are any dependent files to examine */
4567 if ( !info->dependentfiles )
4570 while ( *info->dependentfiles[i] ) {
4571 if ( strequal(file, info->dependentfiles[i]) )
4580 /**********************************************************************
4581 Utility function to remove the dependent file pointed to by the
4582 input parameter from the list
4583 *********************************************************************/
4585 static void trim_dependent_file( fstring files[], int idx )
4588 /* bump everything down a slot */
4590 while( *files[idx+1] ) {
4591 fstrcpy( files[idx], files[idx+1] );
4600 /**********************************************************************
4601 Check if any of the files used by src are also used by drv
4602 *********************************************************************/
4604 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4605 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4607 BOOL in_use = False;
4613 /* check each file. Remove it from the src structure if it overlaps */
4615 if ( drv_file_in_use(src->driverpath, drv) ) {
4617 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4618 fstrcpy( src->driverpath, "" );
4621 if ( drv_file_in_use(src->datafile, drv) ) {
4623 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4624 fstrcpy( src->datafile, "" );
4627 if ( drv_file_in_use(src->configfile, drv) ) {
4629 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4630 fstrcpy( src->configfile, "" );
4633 if ( drv_file_in_use(src->helpfile, drv) ) {
4635 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4636 fstrcpy( src->helpfile, "" );
4639 /* are there any dependentfiles to examine? */
4641 if ( !src->dependentfiles )
4644 while ( *src->dependentfiles[i] ) {
4645 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4647 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4648 trim_dependent_file( src->dependentfiles, i );
4656 /****************************************************************************
4657 Determine whether or not a particular driver files are currently being
4658 used by any other driver.
4660 Return value is True if any files were in use by other drivers
4661 and False otherwise.
4663 Upon return, *info has been modified to only contain the driver files
4664 which are not in use
4665 ****************************************************************************/
4667 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4672 fstring *list = NULL;
4673 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4678 version = info->cversion;
4680 /* loop over all driver versions */
4682 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4684 /* get the list of drivers */
4687 ndrivers = get_ntdrivers(&list, info->environment, version);
4689 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4690 ndrivers, info->environment, version));
4692 /* check each driver for overlap in files */
4694 for (i=0; i<ndrivers; i++) {
4695 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4697 ZERO_STRUCT(driver);
4699 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4704 /* check if d2 uses any files from d1 */
4705 /* only if this is a different driver than the one being deleted */
4707 if ( !strequal(info->name, driver.info_3->name) ) {
4708 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4709 free_a_printer_driver(driver, 3);
4715 free_a_printer_driver(driver, 3);
4720 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4722 driver.info_3 = info;
4724 if ( DEBUGLEVEL >= 20 )
4725 dump_a_printer_driver( driver, 3 );
4730 /****************************************************************************
4731 Actually delete the driver files. Make sure that
4732 printer_driver_files_in_use() return False before calling
4734 ****************************************************************************/
4736 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4740 connection_struct *conn;
4750 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4753 * Connect to the print$ share under the same account as the
4754 * user connected to the rpc pipe. Note we must be root to
4758 null_pw = data_blob( NULL, 0 );
4759 fstrcpy(res_type, "A:");
4761 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4765 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4769 /* Save who we are - we are temporarily becoming the connection user. */
4771 if ( !become_user(conn, conn->vuid) ) {
4772 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4776 /* now delete the files; must strip the '\print$' string from
4779 if ( *info_3->driverpath ) {
4780 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4781 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4782 DEBUG(10,("deleting driverfile [%s]\n", s));
4783 unlink_internals(conn, 0, s);
4787 if ( *info_3->configfile ) {
4788 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4789 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4790 DEBUG(10,("deleting configfile [%s]\n", s));
4791 unlink_internals(conn, 0, s);
4795 if ( *info_3->datafile ) {
4796 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4797 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4798 DEBUG(10,("deleting datafile [%s]\n", s));
4799 unlink_internals(conn, 0, s);
4803 if ( *info_3->helpfile ) {
4804 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4805 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4806 DEBUG(10,("deleting helpfile [%s]\n", s));
4807 unlink_internals(conn, 0, s);
4811 /* check if we are done removing files */
4813 if ( info_3->dependentfiles ) {
4814 while ( *info_3->dependentfiles[i] ) {
4817 /* bypass the "\print$" portion of the path */
4819 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4820 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4821 DEBUG(10,("deleting dependent file [%s]\n", file));
4822 unlink_internals(conn, 0, file );
4834 /****************************************************************************
4835 Remove a printer driver from the TDB. This assumes that the the driver was
4836 previously looked up.
4837 ***************************************************************************/
4839 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4840 uint32 version, BOOL delete_files )
4844 TDB_DATA kbuf, dbuf;
4845 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4847 /* delete the tdb data first */
4849 arch = get_short_archi(info_3->environment);
4850 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4851 arch, version, info_3->name);
4853 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4854 key, delete_files ? "TRUE" : "FALSE" ));
4856 ctr.info_3 = info_3;
4857 dump_a_printer_driver( ctr, 3 );
4860 kbuf.dsize=strlen(key)+1;
4862 /* check if the driver actually exists for this environment */
4864 dbuf = tdb_fetch( tdb_drivers, kbuf );
4866 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4867 return WERR_UNKNOWN_PRINTER_DRIVER;
4870 SAFE_FREE( dbuf.dptr );
4872 /* ok... the driver exists so the delete should return success */
4874 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4875 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4876 return WERR_ACCESS_DENIED;
4880 * now delete any associated files if delete_files == True
4881 * even if this part failes, we return succes because the
4882 * driver doesn not exist any more
4886 delete_driver_files( info_3, user );
4889 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4894 /****************************************************************************
4895 Store a security desc for a printer.
4896 ****************************************************************************/
4898 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4900 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4901 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4903 TALLOC_CTX *mem_ctx = NULL;
4907 mem_ctx = talloc_init("nt_printing_setsec");
4908 if (mem_ctx == NULL)
4911 /* The old owner and group sids of the security descriptor are not
4912 present when new ACEs are added or removed by changing printer
4913 permissions through NT. If they are NULL in the new security
4914 descriptor then copy them over from the old one. */
4916 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4917 DOM_SID *owner_sid, *group_sid;
4918 SEC_ACL *dacl, *sacl;
4919 SEC_DESC *psd = NULL;
4922 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4924 /* Pick out correct owner and group sids */
4926 owner_sid = secdesc_ctr->sec->owner_sid ?
4927 secdesc_ctr->sec->owner_sid :
4928 old_secdesc_ctr->sec->owner_sid;
4930 group_sid = secdesc_ctr->sec->grp_sid ?
4931 secdesc_ctr->sec->grp_sid :
4932 old_secdesc_ctr->sec->grp_sid;
4934 dacl = secdesc_ctr->sec->dacl ?
4935 secdesc_ctr->sec->dacl :
4936 old_secdesc_ctr->sec->dacl;
4938 sacl = secdesc_ctr->sec->sacl ?
4939 secdesc_ctr->sec->sacl :
4940 old_secdesc_ctr->sec->sacl;
4942 /* Make a deep copy of the security descriptor */
4944 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4945 owner_sid, group_sid,
4950 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4953 if (!new_secdesc_ctr) {
4954 new_secdesc_ctr = secdesc_ctr;
4957 /* Store the security descriptor in a tdb */
4959 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4960 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4962 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4964 status = WERR_BADFUNC;
4968 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4970 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4973 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4974 status = WERR_BADFUNC;
4977 /* Free malloc'ed memory */
4983 talloc_destroy(mem_ctx);
4987 /****************************************************************************
4988 Construct a default security descriptor buffer for a printer.
4989 ****************************************************************************/
4991 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4993 SEC_ACE ace[5]; /* max number of ace entries */
4996 SEC_ACL *psa = NULL;
4997 SEC_DESC_BUF *sdb = NULL;
4998 SEC_DESC *psd = NULL;
5002 /* Create an ACE where Everyone is allowed to print */
5004 init_sec_access(&sa, PRINTER_ACE_PRINT);
5005 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5006 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5008 /* Make the security descriptor owned by the Administrators group
5009 on the PDC of the domain. */
5011 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5012 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5015 /* Backup plan - make printer owned by admins.
5016 This should emulate a lanman printer as security
5017 settings can't be changed. */
5019 sid_copy(&owner_sid, get_global_sam_sid());
5020 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5023 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5024 init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5025 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
5026 SEC_ACE_FLAG_INHERIT_ONLY);
5028 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5029 init_sec_ace(&ace[i++], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5030 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5032 /* Add the domain admins group if we are a DC */
5035 DOM_SID domadmins_sid;
5037 sid_copy(&domadmins_sid, get_global_sam_sid());
5038 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5040 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5041 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5042 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
5043 SEC_ACE_FLAG_INHERIT_ONLY);
5045 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5046 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5047 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5050 /* The ACL revision number in rpc_secdesc.h differs from the one
5051 created by NT when setting ACE entries in printer
5052 descriptors. NT4 complains about the property being edited by a
5055 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5056 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5058 NULL, psa, &sd_size);
5062 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5066 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5068 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5069 (unsigned int)sd_size));
5074 /****************************************************************************
5075 Get a security desc for a printer.
5076 ****************************************************************************/
5078 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
5084 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
5085 printername = temp + 1;
5088 /* Fetch security descriptor from tdb */
5090 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
5092 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5093 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5095 DEBUG(4,("using default secdesc for %s\n", printername));
5097 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5101 /* Save default security descriptor for later */
5103 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5104 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5106 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5107 tdb_prs_store(tdb_printers, key, &ps);
5114 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5115 this security descriptor has been created when winbindd was
5116 down. Take ownership of security descriptor. */
5118 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5121 /* Change sd owner to workgroup administrator */
5123 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5124 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5125 SEC_DESC *psd = NULL;
5130 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5132 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5134 (*secdesc_ctr)->sec->grp_sid,
5135 (*secdesc_ctr)->sec->sacl,
5136 (*secdesc_ctr)->sec->dacl,
5139 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5141 /* Swap with other one */
5143 *secdesc_ctr = new_secdesc_ctr;
5147 nt_printing_setsec(printername, *secdesc_ctr);
5151 if (DEBUGLEVEL >= 10) {
5152 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5155 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5156 printername, the_acl->num_aces));
5158 for (i = 0; i < the_acl->num_aces; i++) {
5161 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5163 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5164 the_acl->ace[i].type, the_acl->ace[i].flags,
5165 the_acl->ace[i].info.mask));
5175 1: level not implemented
5176 2: file doesn't exist
5177 3: can't allocate memory
5178 4: can't free memory
5179 5: non existant struct
5183 A printer and a printer driver are 2 different things.
5184 NT manages them separatelly, Samba does the same.
5185 Why ? Simply because it's easier and it makes sense !
5187 Now explanation: You have 3 printers behind your samba server,
5188 2 of them are the same make and model (laser A and B). But laser B
5189 has an 3000 sheet feeder and laser A doesn't such an option.
5190 Your third printer is an old dot-matrix model for the accounting :-).
5192 If the /usr/local/samba/lib directory (default dir), you will have
5193 5 files to describe all of this.
5195 3 files for the printers (1 by printer):
5198 NTprinter_accounting
5199 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5200 NTdriver_printer model X
5201 NTdriver_printer model Y
5203 jfm: I should use this comment for the text file to explain
5204 same thing for the forms BTW.
5205 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5209 /* Convert generic access rights to printer object specific access rights.
5210 It turns out that NT4 security descriptors use generic access rights and
5211 NT5 the object specific ones. */
5213 void map_printer_permissions(SEC_DESC *sd)
5217 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5218 se_map_generic(&sd->dacl->ace[i].info.mask,
5219 &printer_generic_mapping);
5223 /****************************************************************************
5224 Check a user has permissions to perform the given operation. We use the
5225 permission constants defined in include/rpc_spoolss.h to check the various
5226 actions we perform when checking printer access.
5228 PRINTER_ACCESS_ADMINISTER:
5229 print_queue_pause, print_queue_resume, update_printer_sec,
5230 update_printer, spoolss_addprinterex_level_2,
5231 _spoolss_setprinterdata
5236 JOB_ACCESS_ADMINISTER:
5237 print_job_delete, print_job_pause, print_job_resume,
5240 Try access control in the following order (for performance reasons):
5241 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5242 2) check security descriptor (bit comparisons in memory)
5243 3) "printer admins" (may result in numerous calls to winbind)
5245 ****************************************************************************/
5246 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5248 SEC_DESC_BUF *secdesc = NULL;
5249 uint32 access_granted;
5253 TALLOC_CTX *mem_ctx = NULL;
5254 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5256 /* If user is NULL then use the current_user structure */
5259 user = ¤t_user;
5261 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5263 if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5267 /* Get printer name */
5269 pname = PRINTERNAME(snum);
5271 if (!pname || !*pname) {
5276 /* Get printer security descriptor */
5278 if(!(mem_ctx = talloc_init("print_access_check"))) {
5283 nt_printing_getsec(mem_ctx, pname, &secdesc);
5285 if (access_type == JOB_ACCESS_ADMINISTER) {
5286 SEC_DESC_BUF *parent_secdesc = secdesc;
5288 /* Create a child security descriptor to check permissions
5289 against. This is because print jobs are child objects
5290 objects of a printer. */
5292 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5294 /* Now this is the bit that really confuses me. The access
5295 type needs to be changed from JOB_ACCESS_ADMINISTER to
5296 PRINTER_ACCESS_ADMINISTER for this to work. Something
5297 to do with the child (job) object becoming like a
5300 access_type = PRINTER_ACCESS_ADMINISTER;
5305 map_printer_permissions(secdesc->sec);
5307 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5308 &access_granted, &status);
5310 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5312 /* see if we need to try the printer admin list */
5314 if ( access_granted == 0 ) {
5315 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5319 talloc_destroy(mem_ctx);
5327 /****************************************************************************
5328 Check the time parameters allow a print operation.
5329 *****************************************************************************/
5331 BOOL print_time_access_check(int snum)
5333 NT_PRINTER_INFO_LEVEL *printer = NULL;
5335 time_t now = time(NULL);
5339 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5342 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5346 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5348 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5351 free_a_printer(&printer, 2);
5359 /****************************************************************************
5360 Fill in the servername sent in the _spoolss_open_printer_ex() call
5361 ****************************************************************************/
5362 char* get_server_name( Printer_entry *printer )
5364 return printer->servername;