2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern struct current_user current_user;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
43 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_4
45 /* Map generic permissions to printer object specific permissions */
47 GENERIC_MAPPING printer_generic_mapping = {
54 STANDARD_MAPPING printer_std_mapping = {
61 /* Map generic permissions to print server object specific permissions */
63 GENERIC_MAPPING printserver_generic_mapping = {
70 STANDARD_MAPPING printserver_std_mapping = {
77 /* We need one default form to support our default printer. Msoft adds the
78 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
79 array index). Letter is always first, so (for the current code) additions
80 always put things in the correct order. */
81 static const nt_forms_struct default_forms[] = {
82 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
84 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
85 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
86 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
87 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
88 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
89 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
90 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
92 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
93 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
94 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
95 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
96 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
97 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
98 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
99 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
100 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
101 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
102 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
103 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
104 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
105 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
106 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
107 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
108 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
109 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
110 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
111 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
112 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
113 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
114 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
115 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
116 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
117 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
118 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
119 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
120 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
121 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
122 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
123 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
124 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
125 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
126 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
127 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
128 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
129 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
131 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
132 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
133 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
134 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
135 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
136 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
137 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
139 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
140 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
141 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
142 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
143 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
144 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
145 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
146 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
147 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
148 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
149 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
150 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
151 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
152 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
153 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
154 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
155 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
156 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
157 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
158 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
159 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
160 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
161 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
162 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
163 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
164 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
165 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
166 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
167 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
168 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
169 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
170 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
171 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
172 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
173 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
174 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
175 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
176 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
177 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
178 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
179 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
180 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
181 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
182 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
183 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
184 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
185 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
186 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
187 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
188 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
189 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
190 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
191 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
192 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
193 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
194 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
195 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
196 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
197 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
198 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
199 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
203 const char *long_archi;
204 const char *short_archi;
208 #define SPL_ARCH_WIN40 "WIN40"
209 #define SPL_ARCH_W32X86 "W32X86"
210 #define SPL_ARCH_W32MIPS "W32MIPS"
211 #define SPL_ARCH_W32ALPHA "W32ALPHA"
212 #define SPL_ARCH_W32PPC "W32PPC"
213 #define SPL_ARCH_IA64 "IA64"
214 #define SPL_ARCH_X64 "x64"
216 static const struct table_node archi_table[]= {
218 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
219 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
220 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
221 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
222 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
223 {"Windows IA64", SPL_ARCH_IA64, 3 },
224 {"Windows x64", SPL_ARCH_X64, 3 },
228 static BOOL upgrade_to_version_3(void)
230 TDB_DATA kbuf, newkey, dbuf;
232 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
234 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
235 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
237 dbuf = tdb_fetch(tdb_drivers, kbuf);
239 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
240 DEBUG(0,("upgrade_to_version_3:moving form\n"));
241 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
246 if (tdb_delete(tdb_drivers, kbuf) != 0) {
247 SAFE_FREE(dbuf.dptr);
248 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
253 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
254 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
255 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
260 if (tdb_delete(tdb_drivers, kbuf) != 0) {
261 SAFE_FREE(dbuf.dptr);
262 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
267 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
268 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
269 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
274 if (tdb_delete(tdb_drivers, kbuf) != 0) {
275 SAFE_FREE(dbuf.dptr);
276 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
281 SAFE_FREE(dbuf.dptr);
287 /*******************************************************************
288 Fix an issue with security descriptors. Printer sec_desc must
289 use more than the generic bits that were previously used
290 in <= 3.0.14a. They must also have a owner and group SID assigned.
291 Otherwise, any printers than have been migrated to a Windows
292 host using printmig.exe will not be accessible.
293 *******************************************************************/
295 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
296 TDB_DATA data, void *state )
299 SEC_DESC_BUF *sd_orig = NULL;
300 SEC_DESC_BUF *sd_new, *sd_store;
301 SEC_DESC *sec, *new_sec;
302 TALLOC_CTX *ctx = state;
304 uint32 sd_size, size_new_sec;
307 if (!data.dptr || data.dsize == 0)
310 if ( strncmp( key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 )
313 /* upgrade the security descriptor */
317 prs_init( &ps, 0, ctx, UNMARSHALL );
318 prs_give_memory( &ps, data.dptr, data.dsize, True );
320 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
321 /* delete bad entries */
322 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key.dptr ));
323 tdb_delete( tdb_printers, key );
329 /* is this even valid? */
334 /* update access masks */
336 for ( i=0; i<sec->dacl->num_aces; i++ ) {
337 switch ( sec->dacl->ace[i].info.mask ) {
338 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
339 sec->dacl->ace[i].info.mask = PRINTER_ACE_PRINT;
342 case GENERIC_ALL_ACCESS:
343 sec->dacl->ace[i].info.mask = PRINTER_ACE_FULL_CONTROL;
346 case READ_CONTROL_ACCESS:
347 sec->dacl->ace[i].info.mask = PRINTER_ACE_MANAGE_DOCUMENTS;
349 default: /* no change */
354 /* create a new SEC_DESC with the appropriate owner and group SIDs */
356 string_to_sid(&sid, "S-1-5-32-544" );
357 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
359 NULL, NULL, &size_new_sec );
360 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
362 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
363 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
369 sd_size = sec_desc_size(sd_store->sec) + sizeof(SEC_DESC_BUF);
370 prs_init(&ps, sd_size, ctx, MARSHALL);
372 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
373 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
377 data.dptr = prs_data_p( &ps );
378 data.dsize = sd_size;
380 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
384 /* 0 to continue and non-zero to stop traversal */
386 return (result == -1);
389 /*******************************************************************
390 *******************************************************************/
392 static BOOL upgrade_to_version_4(void)
397 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
399 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
402 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
404 talloc_destroy( ctx );
406 return ( result != -1 );
409 /****************************************************************************
410 Open the NT printing tdbs. Done once before fork().
411 ****************************************************************************/
413 BOOL nt_printing_init(void)
415 const char *vstring = "INFO/version";
419 if ( tdb_drivers && tdb_printers && tdb_forms )
423 tdb_close(tdb_drivers);
424 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
426 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
427 lock_path("ntdrivers.tdb"), strerror(errno) ));
432 tdb_close(tdb_printers);
433 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
435 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
436 lock_path("ntprinters.tdb"), strerror(errno) ));
441 tdb_close(tdb_forms);
442 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
444 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
445 lock_path("ntforms.tdb"), strerror(errno) ));
449 /* handle a Samba upgrade */
450 tdb_lock_bystring(tdb_drivers, vstring, 0);
452 /* ---------------- Start Lock Region ---------------- */
454 /* Cope with byte-reversed older versions of the db. */
455 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
457 if ( vers_id != NTDRIVERS_DATABASE_VERSION ) {
459 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
460 /* Written on a bigendian machine with old fetch_int code. Save as le. */
461 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
462 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
463 vers_id = NTDRIVERS_DATABASE_VERSION_3;
466 if (vers_id != NTDRIVERS_DATABASE_VERSION_3 ) {
468 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
469 if (!upgrade_to_version_3())
472 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
474 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
477 /* at this point we know that the database is at version 3 so upgrade to v4 */
479 if ( !upgrade_to_version_4() )
481 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
484 /* ---------------- End Lock Region ------------------ */
486 tdb_unlock_bystring(tdb_drivers, vstring);
488 update_c_setprinter(True);
491 * register callback to handle updating printers as new
492 * drivers are installed
495 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
498 * register callback to handle updating printer data
499 * when a driver is initialized
502 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
505 * register callback to handle invalidating the printer cache
506 * between smbd processes.
509 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
511 /* of course, none of the message callbacks matter if you don't
512 tell messages.c that you interested in receiving PRINT_GENERAL
513 msgs. This is done in claim_connection() */
516 if ( lp_security() == SEC_ADS ) {
517 win_rc = check_published_printers();
518 if (!W_ERROR_IS_OK(win_rc))
519 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
525 /*******************************************************************
526 Function to allow filename parsing "the old way".
527 ********************************************************************/
529 static BOOL driver_unix_convert(char *name,connection_struct *conn,
530 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
533 unix_clean_name(name);
534 trim_string(name,"/","/");
535 return unix_convert(name, conn, saved_last_component, bad_path, pst);
538 /*******************************************************************
539 tdb traversal function for counting printers.
540 ********************************************************************/
542 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
543 TDB_DATA data, void *context)
545 int *printer_count = (int*)context;
547 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
549 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
555 /*******************************************************************
556 Update the spooler global c_setprinter. This variable is initialized
557 when the parent smbd starts with the number of existing printers. It
558 is monotonically increased by the current number of printers *after*
559 each add or delete printer RPC. Only Microsoft knows why... JRR020119
560 ********************************************************************/
562 uint32 update_c_setprinter(BOOL initialize)
565 int32 printer_count = 0;
567 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
569 /* Traverse the tdb, counting the printers */
570 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
572 /* If initializing, set c_setprinter to current printers count
573 * otherwise, bump it by the current printer count
576 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
578 c_setprinter = printer_count;
580 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
581 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
583 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
585 return (uint32)c_setprinter;
588 /*******************************************************************
589 Get the spooler global c_setprinter, accounting for initialization.
590 ********************************************************************/
592 uint32 get_c_setprinter(void)
594 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
596 if (c_setprinter == (int32)-1)
597 c_setprinter = update_c_setprinter(True);
599 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
601 return (uint32)c_setprinter;
604 /****************************************************************************
605 Get builtin form struct list.
606 ****************************************************************************/
608 int get_builtin_ntforms(nt_forms_struct **list)
610 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
611 return sizeof(default_forms) / sizeof(default_forms[0]);
614 /****************************************************************************
615 get a builtin form struct
616 ****************************************************************************/
618 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
622 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
623 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
624 count = sizeof(default_forms) / sizeof(default_forms[0]);
625 for (i=0;i<count;i++) {
626 if (strequal(form_name,default_forms[i].name)) {
627 DEBUGADD(6,("Found builtin form %s \n", form_name));
628 memcpy(form,&default_forms[i],sizeof(*form));
636 /****************************************************************************
637 get a form struct list
638 ****************************************************************************/
639 int get_ntforms(nt_forms_struct **list)
641 TDB_DATA kbuf, newkey, dbuf;
643 nt_forms_struct form;
648 for (kbuf = tdb_firstkey(tdb_forms);
650 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
652 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
655 dbuf = tdb_fetch(tdb_forms, kbuf);
659 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
660 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
661 &i, &form.flag, &form.width, &form.length, &form.left,
662 &form.top, &form.right, &form.bottom);
663 SAFE_FREE(dbuf.dptr);
664 if (ret != dbuf.dsize)
667 tl = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
669 DEBUG(0,("get_ntforms: Realloc fail.\n"));
681 /****************************************************************************
682 write a form struct list
683 ****************************************************************************/
684 int write_ntforms(nt_forms_struct **list, int number)
691 for (i=0;i<number;i++) {
692 /* save index, so list is rebuilt in correct order */
693 len = tdb_pack(buf, sizeof(buf), "dddddddd",
694 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
695 (*list)[i].left, (*list)[i].top, (*list)[i].right,
697 if (len > sizeof(buf)) break;
698 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
699 kbuf.dsize = strlen(key)+1;
703 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
709 /****************************************************************************
710 add a form struct at the end of the list
711 ****************************************************************************/
712 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
720 * NT tries to add forms even when
721 * they are already in the base
722 * only update the values if already present
727 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
728 for (n=0; n<*count; n++) {
729 if ( strequal((*list)[n].name, form_name) ) {
736 if((tl=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
737 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
741 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
745 (*list)[n].flag=form->flags;
746 (*list)[n].width=form->size_x;
747 (*list)[n].length=form->size_y;
748 (*list)[n].left=form->left;
749 (*list)[n].top=form->top;
750 (*list)[n].right=form->right;
751 (*list)[n].bottom=form->bottom;
753 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
754 update ? "updated" : "added", form_name));
759 /****************************************************************************
760 Delete a named form struct.
761 ****************************************************************************/
763 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
772 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
774 for (n=0; n<*count; n++) {
775 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
776 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
782 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
783 *ret = WERR_INVALID_PARAM;
787 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
788 kbuf.dsize = strlen(key)+1;
790 if (tdb_delete(tdb_forms, kbuf) != 0) {
798 /****************************************************************************
799 Update a form struct.
800 ****************************************************************************/
802 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
806 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
808 DEBUG(106, ("[%s]\n", form_name));
809 for (n=0; n<count; n++) {
810 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
811 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
815 if (n==count) return;
817 (*list)[n].flag=form->flags;
818 (*list)[n].width=form->size_x;
819 (*list)[n].length=form->size_y;
820 (*list)[n].left=form->left;
821 (*list)[n].top=form->top;
822 (*list)[n].right=form->right;
823 (*list)[n].bottom=form->bottom;
826 /****************************************************************************
827 Get the nt drivers list.
828 Traverse the database and look-up the matching names.
829 ****************************************************************************/
830 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
833 const char *short_archi;
836 TDB_DATA kbuf, newkey;
838 short_archi = get_short_archi(architecture);
839 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
841 for (kbuf = tdb_firstkey(tdb_drivers);
843 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
845 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
848 if((fl = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
849 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
854 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
861 /****************************************************************************
862 function to do the mapping between the long architecture name and
864 ****************************************************************************/
865 const char *get_short_archi(const char *long_archi)
869 DEBUG(107,("Getting architecture dependant directory\n"));
872 } while ( (archi_table[i].long_archi!=NULL ) &&
873 StrCaseCmp(long_archi, archi_table[i].long_archi) );
875 if (archi_table[i].long_archi==NULL) {
876 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
880 /* this might be client code - but shouldn't this be an fstrcpy etc? */
883 DEBUGADD(108,("index: [%d]\n", i));
884 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
885 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
887 return archi_table[i].short_archi;
890 /****************************************************************************
891 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
892 There are two case to be covered here: PE (Portable Executable) and NE (New
893 Executable) files. Both files support the same INFO structure, but PE files
894 store the signature in unicode, and NE files store it as !unicode.
895 returns -1 on error, 1 on version info found, and 0 on no version info found.
896 ****************************************************************************/
898 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
904 if ((buf=SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
905 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
906 fname, PE_HEADER_SIZE));
910 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
911 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
912 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
913 fname, (unsigned long)byte_count));
914 goto no_version_info;
917 /* Is this really a DOS header? */
918 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
919 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
920 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
921 goto no_version_info;
924 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
925 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
926 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
928 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
929 goto no_version_info;
932 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
933 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
934 fname, (unsigned long)byte_count));
935 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
936 goto no_version_info;
939 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
940 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
941 unsigned int num_sections;
942 unsigned int section_table_bytes;
944 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
945 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
946 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
947 /* At this point, we assume the file is in error. It still could be somthing
948 * else besides a PE file, but it unlikely at this point.
953 /* get the section table */
954 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
955 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
956 if (section_table_bytes == 0)
960 if ((buf=SMB_MALLOC(section_table_bytes)) == NULL) {
961 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
962 fname, section_table_bytes));
966 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
967 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
968 fname, (unsigned long)byte_count));
972 /* Iterate the section table looking for the resource section ".rsrc" */
973 for (i = 0; i < num_sections; i++) {
974 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
976 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
977 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
978 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
980 if (section_bytes == 0)
984 if ((buf=SMB_MALLOC(section_bytes)) == NULL) {
985 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
986 fname, section_bytes));
990 /* Seek to the start of the .rsrc section info */
991 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
992 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
997 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
998 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
999 fname, (unsigned long)byte_count));
1003 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1006 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1007 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1008 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1009 /* Align to next long address */
1010 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1012 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1013 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1014 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1016 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1017 fname, *major, *minor,
1018 (*major>>16)&0xffff, *major&0xffff,
1019 (*minor>>16)&0xffff, *minor&0xffff));
1028 /* Version info not found, fall back to origin date/time */
1029 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1033 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1034 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1035 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1036 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1037 /* At this point, we assume the file is in error. It still could be somthing
1038 * else besides a NE file, but it unlikely at this point. */
1042 /* Allocate a bit more space to speed up things */
1044 if ((buf=SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1045 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1046 fname, PE_HEADER_SIZE));
1050 /* This is a HACK! I got tired of trying to sort through the messy
1051 * 'NE' file format. If anyone wants to clean this up please have at
1052 * it, but this works. 'NE' files will eventually fade away. JRR */
1053 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1054 /* Cover case that should not occur in a well formed 'NE' .dll file */
1055 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1057 for(i=0; i<byte_count; i++) {
1058 /* Fast skip past data that can't possibly match */
1059 if (buf[i] != 'V') continue;
1061 /* Potential match data crosses buf boundry, move it to beginning
1062 * of buf, and fill the buf with as much as it will hold. */
1063 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1066 memcpy(buf, &buf[i], byte_count-i);
1067 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1068 (byte_count-i))) < 0) {
1070 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1075 byte_count = bc + (byte_count - i);
1076 if (byte_count<VS_VERSION_INFO_SIZE) break;
1081 /* Check that the full signature string and the magic number that
1082 * follows exist (not a perfect solution, but the chances that this
1083 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1084 * twice, as it is simpler to read the code. */
1085 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1086 /* Compute skip alignment to next long address */
1087 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
1088 sizeof(VS_SIGNATURE)) & 3;
1089 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1091 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1092 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1093 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1094 fname, *major, *minor,
1095 (*major>>16)&0xffff, *major&0xffff,
1096 (*minor>>16)&0xffff, *minor&0xffff));
1103 /* Version info not found, fall back to origin date/time */
1104 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1109 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1110 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1111 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1122 /****************************************************************************
1123 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1124 share one or more files. During the MS installation process files are checked
1125 to insure that only a newer version of a shared file is installed over an
1126 older version. There are several possibilities for this comparison. If there
1127 is no previous version, the new one is newer (obviously). If either file is
1128 missing the version info structure, compare the creation date (on Unix use
1129 the modification date). Otherwise chose the numerically larger version number.
1130 ****************************************************************************/
1132 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1134 BOOL use_version = True;
1139 time_t new_create_time;
1143 time_t old_create_time;
1147 files_struct *fsp = NULL;
1149 SMB_STRUCT_STAT stat_buf;
1152 SET_STAT_INVALID(st);
1153 SET_STAT_INVALID(stat_buf);
1154 new_create_time = (time_t)0;
1155 old_create_time = (time_t)0;
1157 /* Get file version info (if available) for previous file (if it exists) */
1158 pstrcpy(filepath, old_file);
1160 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1162 fsp = open_file_shared(conn, filepath, &stat_buf,
1163 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1164 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1165 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1167 /* Old file not found, so by definition new file is in fact newer */
1168 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1173 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1174 if (ret == -1) goto error_exit;
1177 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1179 use_version = False;
1180 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1181 old_create_time = st.st_mtime;
1182 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1185 close_file(fsp, True);
1187 /* Get file version info (if available) for new file */
1188 pstrcpy(filepath, new_file);
1189 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1191 fsp = open_file_shared(conn, filepath, &stat_buf,
1192 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1193 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1194 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1196 /* New file not found, this shouldn't occur if the caller did its job */
1197 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1202 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1203 if (ret == -1) goto error_exit;
1206 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1208 use_version = False;
1209 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1210 new_create_time = st.st_mtime;
1211 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1214 close_file(fsp, True);
1216 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1217 /* Compare versions and choose the larger version number */
1218 if (new_major > old_major ||
1219 (new_major == old_major && new_minor > old_minor)) {
1221 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1225 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1230 /* Compare modification time/dates and choose the newest time/date */
1231 if (new_create_time > old_create_time) {
1232 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1236 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1243 close_file(fsp, True);
1247 /****************************************************************************
1248 Determine the correct cVersion associated with an architecture and driver
1249 ****************************************************************************/
1250 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1251 struct current_user *user, WERROR *perr)
1260 files_struct *fsp = NULL;
1263 connection_struct *conn;
1265 SET_STAT_INVALID(st);
1267 *perr = WERR_INVALID_PARAM;
1269 /* If architecture is Windows 95/98/ME, the version is always 0. */
1270 if (strcmp(architecture, "WIN40") == 0) {
1271 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1277 * Connect to the print$ share under the same account as the user connected
1278 * to the rpc pipe. Note we must still be root to do this.
1281 /* Null password is ok - we are already an authenticated user... */
1282 null_pw = data_blob(NULL, 0);
1283 fstrcpy(res_type, "A:");
1285 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1289 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1290 *perr = ntstatus_to_werror(nt_status);
1294 /* We are temporarily becoming the connection user. */
1295 if (!become_user(conn, user->vuid)) {
1296 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1297 *perr = WERR_ACCESS_DENIED;
1301 /* Open the driver file (Portable Executable format) and determine the
1302 * deriver the cversion. */
1303 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1305 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1307 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1308 *perr = WERR_BADFILE;
1312 fsp = open_file_shared(conn, driverpath, &st,
1313 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1314 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1315 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1318 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1319 driverpath, errno));
1320 *perr = WERR_ACCESS_DENIED;
1326 int ret = get_file_version(fsp, driverpath, &major, &minor);
1327 if (ret == -1) goto error_exit;
1330 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1335 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1336 * for more details. Version in this case is not just the version of the
1337 * file, but the version in the sense of kernal mode (2) vs. user mode
1338 * (3) drivers. Other bits of the version fields are the version info.
1341 cversion = major & 0x0000ffff;
1343 case 2: /* WinNT drivers */
1344 case 3: /* Win2K drivers */
1348 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1349 driverpath, cversion));
1353 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1354 driverpath, major, minor));
1357 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1358 driverpath, cversion));
1360 close_file(fsp, True);
1361 close_cnum(conn, user->vuid);
1370 close_file(fsp, True);
1372 close_cnum(conn, user->vuid);
1377 /****************************************************************************
1378 ****************************************************************************/
1379 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1380 struct current_user *user)
1382 const char *architecture;
1388 /* clean up the driver name.
1389 * we can get .\driver.dll
1390 * or worse c:\windows\system\driver.dll !
1392 /* using an intermediate string to not have overlaping memcpy()'s */
1393 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1394 fstrcpy(new_name, p+1);
1395 fstrcpy(driver->driverpath, new_name);
1398 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1399 fstrcpy(new_name, p+1);
1400 fstrcpy(driver->datafile, new_name);
1403 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1404 fstrcpy(new_name, p+1);
1405 fstrcpy(driver->configfile, new_name);
1408 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1409 fstrcpy(new_name, p+1);
1410 fstrcpy(driver->helpfile, new_name);
1413 if (driver->dependentfiles) {
1414 for (i=0; *driver->dependentfiles[i]; i++) {
1415 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1416 fstrcpy(new_name, p+1);
1417 fstrcpy(driver->dependentfiles[i], new_name);
1422 architecture = get_short_archi(driver->environment);
1424 /* jfm:7/16/2000 the client always sends the cversion=0.
1425 * The server should check which version the driver is by reading
1426 * the PE header of driver->driverpath.
1428 * For Windows 95/98 the version is 0 (so the value sent is correct)
1429 * For Windows NT (the architecture doesn't matter)
1430 * NT 3.1: cversion=0
1431 * NT 3.5/3.51: cversion=1
1435 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1441 /****************************************************************************
1442 ****************************************************************************/
1443 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1445 const char *architecture;
1451 /* clean up the driver name.
1452 * we can get .\driver.dll
1453 * or worse c:\windows\system\driver.dll !
1455 /* using an intermediate string to not have overlaping memcpy()'s */
1456 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1457 fstrcpy(new_name, p+1);
1458 fstrcpy(driver->driverpath, new_name);
1461 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1462 fstrcpy(new_name, p+1);
1463 fstrcpy(driver->datafile, new_name);
1466 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1467 fstrcpy(new_name, p+1);
1468 fstrcpy(driver->configfile, new_name);
1471 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1472 fstrcpy(new_name, p+1);
1473 fstrcpy(driver->helpfile, new_name);
1476 if (driver->dependentfiles) {
1477 for (i=0; *driver->dependentfiles[i]; i++) {
1478 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1479 fstrcpy(new_name, p+1);
1480 fstrcpy(driver->dependentfiles[i], new_name);
1485 architecture = get_short_archi(driver->environment);
1487 /* jfm:7/16/2000 the client always sends the cversion=0.
1488 * The server should check which version the driver is by reading
1489 * the PE header of driver->driverpath.
1491 * For Windows 95/98 the version is 0 (so the value sent is correct)
1492 * For Windows NT (the architecture doesn't matter)
1493 * NT 3.1: cversion=0
1494 * NT 3.5/3.51: cversion=1
1499 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1505 /****************************************************************************
1506 ****************************************************************************/
1507 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1508 uint32 level, struct current_user *user)
1513 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1514 driver=driver_abstract.info_3;
1515 return clean_up_driver_struct_level_3(driver, user);
1519 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1520 driver=driver_abstract.info_6;
1521 return clean_up_driver_struct_level_6(driver, user);
1524 return WERR_INVALID_PARAM;
1528 /****************************************************************************
1529 This function sucks and should be replaced. JRA.
1530 ****************************************************************************/
1532 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1534 dst->cversion = src->version;
1536 fstrcpy( dst->name, src->name);
1537 fstrcpy( dst->environment, src->environment);
1538 fstrcpy( dst->driverpath, src->driverpath);
1539 fstrcpy( dst->datafile, src->datafile);
1540 fstrcpy( dst->configfile, src->configfile);
1541 fstrcpy( dst->helpfile, src->helpfile);
1542 fstrcpy( dst->monitorname, src->monitorname);
1543 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1544 dst->dependentfiles = src->dependentfiles;
1547 #if 0 /* Debugging function */
1549 static char* ffmt(unsigned char *c){
1551 static char ffmt_str[17];
1553 for (i=0; i<16; i++) {
1554 if ((c[i] < ' ') || (c[i] > '~'))
1565 /****************************************************************************
1566 ****************************************************************************/
1567 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1568 struct current_user *user, WERROR *perr)
1570 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1571 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1572 const char *architecture;
1577 connection_struct *conn;
1588 memset(inbuf, '\0', sizeof(inbuf));
1589 memset(outbuf, '\0', sizeof(outbuf));
1593 driver=driver_abstract.info_3;
1594 else if (level==6) {
1595 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1596 driver = &converted_driver;
1598 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1599 return WERR_UNKNOWN_LEVEL;
1602 architecture = get_short_archi(driver->environment);
1605 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1606 * Note we must be root to do this.
1609 null_pw = data_blob(NULL, 0);
1610 fstrcpy(res_type, "A:");
1612 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1616 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1617 *perr = ntstatus_to_werror(nt_status);
1618 return WERR_NO_SUCH_SHARE;
1622 * Save who we are - we are temporarily becoming the connection user.
1625 if (!become_user(conn, conn->vuid)) {
1626 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1627 return WERR_ACCESS_DENIED;
1631 * make the directories version and version\driver_name
1632 * under the architecture directory.
1634 DEBUG(5,("Creating first directory\n"));
1635 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1636 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1637 mkdir_internal(conn, new_dir, bad_path);
1639 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1640 * listed for this driver which has already been moved, skip it (note:
1641 * drivers may list the same file name several times. Then check if the
1642 * file already exists in archi\cversion\, if so, check that the version
1643 * info (or time stamps if version info is unavailable) is newer (or the
1644 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1645 * Otherwise, delete the file.
1647 * If a file is not moved to archi\cversion\ because of an error, all the
1648 * rest of the 'unmoved' driver files are removed from archi\. If one or
1649 * more of the driver's files was already moved to archi\cversion\, it
1650 * potentially leaves the driver in a partially updated state. Version
1651 * trauma will most likely occur if an client attempts to use any printer
1652 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1653 * done is appropriate... later JRR
1656 DEBUG(5,("Moving files now !\n"));
1658 if (driver->driverpath && strlen(driver->driverpath)) {
1659 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1660 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1661 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1662 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1663 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1664 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1665 new_name, old_name));
1666 *perr = WERR_ACCESS_DENIED;
1672 if (driver->datafile && strlen(driver->datafile)) {
1673 if (!strequal(driver->datafile, driver->driverpath)) {
1674 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1675 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1676 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1677 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1678 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1679 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1680 new_name, old_name));
1681 *perr = WERR_ACCESS_DENIED;
1688 if (driver->configfile && strlen(driver->configfile)) {
1689 if (!strequal(driver->configfile, driver->driverpath) &&
1690 !strequal(driver->configfile, driver->datafile)) {
1691 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1692 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1693 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1694 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1695 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1696 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1697 new_name, old_name));
1698 *perr = WERR_ACCESS_DENIED;
1705 if (driver->helpfile && strlen(driver->helpfile)) {
1706 if (!strequal(driver->helpfile, driver->driverpath) &&
1707 !strequal(driver->helpfile, driver->datafile) &&
1708 !strequal(driver->helpfile, driver->configfile)) {
1709 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1710 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1711 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1712 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1713 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1714 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1715 new_name, old_name));
1716 *perr = WERR_ACCESS_DENIED;
1723 if (driver->dependentfiles) {
1724 for (i=0; *driver->dependentfiles[i]; i++) {
1725 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1726 !strequal(driver->dependentfiles[i], driver->datafile) &&
1727 !strequal(driver->dependentfiles[i], driver->configfile) &&
1728 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1730 for (j=0; j < i; j++) {
1731 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1736 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1737 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1738 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1739 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1740 if ( !copy_file(new_name, old_name, conn, FILE_EXISTS_TRUNCATE|FILE_CREATE_IF_NOT_EXIST, 0, False, &err) ) {
1741 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1742 new_name, old_name));
1743 *perr = WERR_ACCESS_DENIED;
1752 close_cnum(conn, user->vuid);
1755 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1763 const char *architecture;
1769 TDB_DATA kbuf, dbuf;
1771 architecture = get_short_archi(driver->environment);
1773 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1774 * \\server is added in the rpc server layer.
1775 * It does make sense to NOT store the server's name in the printer TDB.
1778 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1780 /* .inf files do not always list a file for each of the four standard files.
1781 * Don't prepend a path to a null filename, or client claims:
1782 * "The server on which the printer resides does not have a suitable
1783 * <printer driver name> printer driver installed. Click OK if you
1784 * wish to install the driver on your local machine."
1786 if (strlen(driver->driverpath)) {
1787 fstrcpy(temp_name, driver->driverpath);
1788 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1791 if (strlen(driver->datafile)) {
1792 fstrcpy(temp_name, driver->datafile);
1793 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1796 if (strlen(driver->configfile)) {
1797 fstrcpy(temp_name, driver->configfile);
1798 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1801 if (strlen(driver->helpfile)) {
1802 fstrcpy(temp_name, driver->helpfile);
1803 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1806 if (driver->dependentfiles) {
1807 for (i=0; *driver->dependentfiles[i]; i++) {
1808 fstrcpy(temp_name, driver->dependentfiles[i]);
1809 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1813 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1815 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1822 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1825 driver->environment,
1830 driver->monitorname,
1831 driver->defaultdatatype);
1833 if (driver->dependentfiles) {
1834 for (i=0; *driver->dependentfiles[i]; i++) {
1835 len += tdb_pack(buf+len, buflen-len, "f",
1836 driver->dependentfiles[i]);
1840 if (len != buflen) {
1843 tb = (char *)SMB_REALLOC(buf, len);
1845 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1856 kbuf.dsize = strlen(key)+1;
1860 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1864 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1870 /****************************************************************************
1871 ****************************************************************************/
1872 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1874 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1877 info3.cversion = driver->version;
1878 fstrcpy(info3.name,driver->name);
1879 fstrcpy(info3.environment,driver->environment);
1880 fstrcpy(info3.driverpath,driver->driverpath);
1881 fstrcpy(info3.datafile,driver->datafile);
1882 fstrcpy(info3.configfile,driver->configfile);
1883 fstrcpy(info3.helpfile,driver->helpfile);
1884 fstrcpy(info3.monitorname,driver->monitorname);
1885 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1886 info3.dependentfiles = driver->dependentfiles;
1888 return add_a_printer_driver_3(&info3);
1892 /****************************************************************************
1893 ****************************************************************************/
1894 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1896 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1900 fstrcpy(info.name, driver);
1901 fstrcpy(info.defaultdatatype, "RAW");
1903 fstrcpy(info.driverpath, "");
1904 fstrcpy(info.datafile, "");
1905 fstrcpy(info.configfile, "");
1906 fstrcpy(info.helpfile, "");
1908 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
1911 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1912 fstrcpy(info.dependentfiles[0], "");
1914 *info_ptr = memdup(&info, sizeof(info));
1919 /****************************************************************************
1920 ****************************************************************************/
1921 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1923 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1924 TDB_DATA kbuf, dbuf;
1925 const char *architecture;
1930 ZERO_STRUCT(driver);
1932 architecture = get_short_archi(arch);
1934 if ( !architecture )
1935 return WERR_UNKNOWN_PRINTER_DRIVER;
1937 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1939 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1942 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1944 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1947 kbuf.dsize = strlen(key)+1;
1949 dbuf = tdb_fetch(tdb_drivers, kbuf);
1951 return WERR_UNKNOWN_PRINTER_DRIVER;
1953 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1962 driver.defaultdatatype);
1965 while (len < dbuf.dsize) {
1968 tddfs = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
1969 if (tddfs == NULL) {
1970 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1973 else driver.dependentfiles = tddfs;
1975 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1976 &driver.dependentfiles[i]);
1980 if (driver.dependentfiles != NULL)
1981 fstrcpy(driver.dependentfiles[i], "");
1983 SAFE_FREE(dbuf.dptr);
1985 if (len != dbuf.dsize) {
1986 SAFE_FREE(driver.dependentfiles);
1988 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1991 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1996 /****************************************************************************
1997 Debugging function, dump at level 6 the struct in the logs.
1998 ****************************************************************************/
2000 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2003 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2006 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2012 if (driver.info_3 == NULL)
2015 info3=driver.info_3;
2017 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2018 DEBUGADD(20,("name:[%s]\n", info3->name));
2019 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2020 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2021 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2022 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2023 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2024 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2025 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2027 for (i=0; info3->dependentfiles &&
2028 *info3->dependentfiles[i]; i++) {
2029 DEBUGADD(20,("dependentfile:[%s]\n",
2030 info3->dependentfiles[i]));
2037 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2045 /****************************************************************************
2046 ****************************************************************************/
2047 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
2051 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2056 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2057 nt_devmode->devicename,
2058 nt_devmode->formname,
2060 nt_devmode->specversion,
2061 nt_devmode->driverversion,
2063 nt_devmode->driverextra,
2064 nt_devmode->orientation,
2065 nt_devmode->papersize,
2066 nt_devmode->paperlength,
2067 nt_devmode->paperwidth,
2070 nt_devmode->defaultsource,
2071 nt_devmode->printquality,
2074 nt_devmode->yresolution,
2075 nt_devmode->ttoption,
2076 nt_devmode->collate,
2077 nt_devmode->logpixels,
2080 nt_devmode->bitsperpel,
2081 nt_devmode->pelswidth,
2082 nt_devmode->pelsheight,
2083 nt_devmode->displayflags,
2084 nt_devmode->displayfrequency,
2085 nt_devmode->icmmethod,
2086 nt_devmode->icmintent,
2087 nt_devmode->mediatype,
2088 nt_devmode->dithertype,
2089 nt_devmode->reserved1,
2090 nt_devmode->reserved2,
2091 nt_devmode->panningwidth,
2092 nt_devmode->panningheight,
2093 nt_devmode->nt_dev_private);
2096 if (nt_devmode->nt_dev_private) {
2097 len += tdb_pack(buf+len, buflen-len, "B",
2098 nt_devmode->driverextra,
2099 nt_devmode->nt_dev_private);
2102 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2107 /****************************************************************************
2108 Pack all values in all printer keys
2109 ***************************************************************************/
2111 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
2115 REGISTRY_VALUE *val;
2116 REGVAL_CTR *val_ctr;
2123 /* loop over all keys */
2125 for ( i=0; i<data->num_keys; i++ ) {
2126 val_ctr = &data->keys[i].values;
2127 num_values = regval_ctr_numvals( val_ctr );
2129 /* pack the keyname followed by a empty value */
2131 len += tdb_pack(buf+len, buflen-len, "pPdB",
2132 &data->keys[i].name,
2138 /* now loop over all values */
2140 for ( j=0; j<num_values; j++ ) {
2141 /* pathname should be stored as <key>\<value> */
2143 val = regval_ctr_specific_value( val_ctr, j );
2144 pstrcpy( path, data->keys[i].name );
2145 pstrcat( path, "\\" );
2146 pstrcat( path, regval_name(val) );
2148 len += tdb_pack(buf+len, buflen-len, "pPdB",
2153 regval_data_p(val) );
2160 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2166 /****************************************************************************
2167 Delete a printer - this just deletes the printer info file, any open
2168 handles are not affected.
2169 ****************************************************************************/
2171 uint32 del_a_printer(const char *sharename)
2175 pstring printdb_path;
2177 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2179 kbuf.dsize=strlen(key)+1;
2180 tdb_delete(tdb_printers, kbuf);
2182 slprintf(key, sizeof(key)-1, "%s%s", SECDESC_PREFIX, sharename);
2184 kbuf.dsize=strlen(key)+1;
2185 tdb_delete(tdb_printers, kbuf);
2187 close_all_print_db();
2189 if (geteuid() == 0) {
2190 pstrcpy(printdb_path, lock_path("printing/"));
2191 pstrcat(printdb_path, sharename);
2192 pstrcat(printdb_path, ".tdb");
2194 unlink(printdb_path);
2200 /****************************************************************************
2201 ****************************************************************************/
2202 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2205 fstring norm_sharename;
2209 TDB_DATA kbuf, dbuf;
2212 * in addprinter: no servername and the printer is the name
2213 * in setprinter: servername is \\server
2214 * and printer is \\server\\printer
2216 * Samba manages only local printers.
2217 * we currently don't support things like i
2218 * path=\\other_server\printer
2220 * We only store the printername, not \\server\printername
2223 if ( info->servername[0] != '\0' ) {
2224 trim_string(info->printername, info->servername, NULL);
2225 trim_char(info->printername, '\\', '\0');
2226 info->servername[0]='\0';
2230 * JFM: one day I'll forget.
2231 * below that's info->portname because that's the SAMBA sharename
2232 * and I made NT 'thinks' it's the portname
2233 * the info->sharename is the thing you can name when you add a printer
2234 * that's the short-name when you create shared printer for 95/98
2235 * So I've made a limitation in SAMBA: you can only have 1 printer model
2236 * behind a SAMBA share.
2244 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2247 info->default_priority,
2264 info->printprocessor,
2268 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2270 len += pack_values( &info->data, buf+len, buflen-len );
2272 if (buflen != len) {
2275 tb = (char *)SMB_REALLOC(buf, len);
2277 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2287 /* normalize the key */
2289 fstrcpy( norm_sharename, info->sharename );
2290 strlower_m( norm_sharename );
2292 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2295 kbuf.dsize = strlen(key)+1;
2299 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2302 if (!W_ERROR_IS_OK(ret))
2303 DEBUG(8, ("error updating printer to tdb on disk\n"));
2307 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2308 info->sharename, info->drivername, info->portname, len));
2314 /****************************************************************************
2315 Malloc and return an NT devicemode.
2316 ****************************************************************************/
2318 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2321 char adevice[MAXDEVICENAME];
2322 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2324 if (nt_devmode == NULL) {
2325 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2329 ZERO_STRUCTP(nt_devmode);
2331 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2332 fstrcpy(nt_devmode->devicename, adevice);
2334 fstrcpy(nt_devmode->formname, "Letter");
2336 nt_devmode->specversion = 0x0401;
2337 nt_devmode->driverversion = 0x0400;
2338 nt_devmode->size = 0x00DC;
2339 nt_devmode->driverextra = 0x0000;
2340 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2341 DEFAULTSOURCE | COPIES | SCALE |
2342 PAPERSIZE | ORIENTATION;
2343 nt_devmode->orientation = 1;
2344 nt_devmode->papersize = PAPER_LETTER;
2345 nt_devmode->paperlength = 0;
2346 nt_devmode->paperwidth = 0;
2347 nt_devmode->scale = 0x64;
2348 nt_devmode->copies = 1;
2349 nt_devmode->defaultsource = BIN_FORMSOURCE;
2350 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2351 nt_devmode->color = COLOR_MONOCHROME;
2352 nt_devmode->duplex = DUP_SIMPLEX;
2353 nt_devmode->yresolution = 0;
2354 nt_devmode->ttoption = TT_SUBDEV;
2355 nt_devmode->collate = COLLATE_FALSE;
2356 nt_devmode->icmmethod = 0;
2357 nt_devmode->icmintent = 0;
2358 nt_devmode->mediatype = 0;
2359 nt_devmode->dithertype = 0;
2361 /* non utilisés par un driver d'imprimante */
2362 nt_devmode->logpixels = 0;
2363 nt_devmode->bitsperpel = 0;
2364 nt_devmode->pelswidth = 0;
2365 nt_devmode->pelsheight = 0;
2366 nt_devmode->displayflags = 0;
2367 nt_devmode->displayfrequency = 0;
2368 nt_devmode->reserved1 = 0;
2369 nt_devmode->reserved2 = 0;
2370 nt_devmode->panningwidth = 0;
2371 nt_devmode->panningheight = 0;
2373 nt_devmode->nt_dev_private = NULL;
2377 /****************************************************************************
2378 Deepcopy an NT devicemode.
2379 ****************************************************************************/
2381 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2383 NT_DEVICEMODE *new_nt_devicemode = NULL;
2385 if ( !nt_devicemode )
2388 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2389 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2393 new_nt_devicemode->nt_dev_private = NULL;
2394 if (nt_devicemode->nt_dev_private != NULL) {
2395 if ((new_nt_devicemode->nt_dev_private = memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2396 SAFE_FREE(new_nt_devicemode);
2397 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2402 return new_nt_devicemode;
2405 /****************************************************************************
2406 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2407 ****************************************************************************/
2409 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2411 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2413 if(nt_devmode == NULL)
2416 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2418 SAFE_FREE(nt_devmode->nt_dev_private);
2419 SAFE_FREE(*devmode_ptr);
2422 /****************************************************************************
2423 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2424 ****************************************************************************/
2425 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2427 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2428 NT_PRINTER_DATA *data;
2434 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2436 free_nt_devicemode(&info->devmode);
2438 /* clean up all registry keys */
2441 for ( i=0; i<data->num_keys; i++ ) {
2442 SAFE_FREE( data->keys[i].name );
2443 regval_ctr_destroy( &data->keys[i].values );
2445 SAFE_FREE( data->keys );
2447 /* finally the top level structure */
2449 SAFE_FREE( *info_ptr );
2453 /****************************************************************************
2454 ****************************************************************************/
2455 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2459 NT_DEVICEMODE devmode;
2461 ZERO_STRUCT(devmode);
2463 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2465 if (!*nt_devmode) return len;
2467 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2471 &devmode.specversion,
2472 &devmode.driverversion,
2474 &devmode.driverextra,
2475 &devmode.orientation,
2477 &devmode.paperlength,
2478 &devmode.paperwidth,
2481 &devmode.defaultsource,
2482 &devmode.printquality,
2485 &devmode.yresolution,
2491 &devmode.bitsperpel,
2493 &devmode.pelsheight,
2494 &devmode.displayflags,
2495 &devmode.displayfrequency,
2499 &devmode.dithertype,
2502 &devmode.panningwidth,
2503 &devmode.panningheight,
2504 &devmode.nt_dev_private);
2506 if (devmode.nt_dev_private) {
2507 /* the len in tdb_unpack is an int value and
2508 * devmode.driverextra is only a short
2510 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2511 devmode.driverextra=(uint16)extra_len;
2513 /* check to catch an invalid TDB entry so we don't segfault */
2514 if (devmode.driverextra == 0) {
2515 devmode.nt_dev_private = NULL;
2519 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2521 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2522 if (devmode.nt_dev_private)
2523 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2528 /****************************************************************************
2529 Allocate and initialize a new slot.
2530 ***************************************************************************/
2532 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2537 if ( !data || !name )
2540 /* allocate another slot in the NT_PRINTER_KEY array */
2542 if ( !(d = SMB_REALLOC_ARRAY( data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2543 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2549 key_index = data->num_keys;
2551 /* initialze new key */
2554 data->keys[key_index].name = SMB_STRDUP( name );
2556 regval_ctr_init( &data->keys[key_index].values );
2558 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2563 /****************************************************************************
2564 search for a registry key name in the existing printer data
2565 ***************************************************************************/
2567 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2570 NT_PRINTER_KEY *printer_key;
2572 for ( i=0; i<data->num_keys; i++ ) {
2573 if ( strequal( data->keys[i].name, name ) ) {
2575 /* cleanup memory */
2577 printer_key = &data->keys[i];
2578 SAFE_FREE( printer_key->name );
2579 regval_ctr_destroy( &printer_key->values );
2581 /* if not the end of the array, move remaining elements down one slot */
2584 if ( data->num_keys && (i < data->num_keys) )
2585 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2592 return data->num_keys;
2595 /****************************************************************************
2596 search for a registry key name in the existing printer data
2597 ***************************************************************************/
2599 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2604 if ( !data || !name )
2607 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2609 /* loop over all existing keys */
2611 for ( i=0; i<data->num_keys; i++ ) {
2612 if ( strequal(data->keys[i].name, name) ) {
2613 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2623 /****************************************************************************
2624 ***************************************************************************/
2626 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2630 int num_subkeys = 0;
2632 fstring *ptr, *subkeys_ptr = NULL;
2641 /* special case of asking for the top level printer data registry key names */
2643 if ( strlen(key) == 0 ) {
2644 for ( i=0; i<data->num_keys; i++ ) {
2646 /* found a match, so allocate space and copy the name */
2648 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2649 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2651 SAFE_FREE( subkeys );
2656 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2663 /* asking for the subkeys of some key */
2664 /* subkey paths are stored in the key name using '\' as the delimiter */
2666 for ( i=0; i<data->num_keys; i++ ) {
2667 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2669 /* if we found the exact key, then break */
2670 key_len = strlen( key );
2671 if ( strlen(data->keys[i].name) == key_len )
2674 /* get subkey path */
2676 p = data->keys[i].name + key_len;
2679 fstrcpy( subkeyname, p );
2680 if ( (p = strchr( subkeyname, '\\' )) )
2683 /* don't add a key more than once */
2685 for ( j=0; j<num_subkeys; j++ ) {
2686 if ( strequal( subkeys_ptr[j], subkeyname ) )
2690 if ( j != num_subkeys )
2693 /* found a match, so allocate space and copy the name */
2695 if ( !(ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2696 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2698 SAFE_FREE( subkeys );
2703 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2709 /* return error if the key was not found */
2711 if ( i == data->num_keys )
2715 /* tag off the end */
2718 fstrcpy(subkeys_ptr[num_subkeys], "" );
2720 *subkeys = subkeys_ptr;
2726 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2729 smb_ucs2_t conv_str[1024];
2732 regval_ctr_delvalue(ctr, val_name);
2733 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2734 STR_TERMINATE | STR_NOALIGN);
2735 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2736 (char *) conv_str, str_size);
2739 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2742 regval_ctr_delvalue(ctr, val_name);
2743 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2744 (char *) &dword, sizeof(dword));
2747 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2750 uint8 bin_bool = (b ? 1 : 0);
2751 regval_ctr_delvalue(ctr, val_name);
2752 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2753 (char *) &bin_bool, sizeof(bin_bool));
2756 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2757 const char *multi_sz)
2759 smb_ucs2_t *conv_strs = NULL;
2762 /* a multi-sz has to have a null string terminator, i.e., the last
2763 string must be followed by two nulls */
2764 str_size = strlen(multi_sz) + 2;
2765 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2770 /* Change to byte units. */
2771 str_size *= sizeof(smb_ucs2_t);
2772 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2773 STR_TERMINATE | STR_NOALIGN);
2775 regval_ctr_delvalue(ctr, val_name);
2776 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2777 (char *) conv_strs, str_size);
2778 safe_free(conv_strs);
2782 /****************************************************************************
2783 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2785 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2786 * @return BOOL indicating success or failure
2787 ***************************************************************************/
2789 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2791 REGVAL_CTR *ctr = NULL;
2794 char *allocated_string = NULL;
2795 const char *ascii_str;
2798 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2799 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2800 ctr = &info2->data.keys[i].values;
2802 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2803 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2805 /* we make the assumption that the netbios name is the same
2806 as the DNS name sinc ethe former will be what we used to
2809 if ( get_mydnsdomname( dnssuffix ) )
2810 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2812 fstrcpy( longname, global_myname() );
2814 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2816 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2817 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2818 SAFE_FREE(allocated_string);
2820 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2821 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2822 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2823 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2824 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2825 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2826 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2827 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2828 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2830 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2831 (info2->attributes &
2832 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2834 switch (info2->attributes & 0x3) {
2836 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2839 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2842 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2845 ascii_str = "unknown";
2847 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2852 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2856 REGVAL_CTR *ctr=NULL;
2858 /* find the DsSpooler key */
2859 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2860 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2861 ctr = &info2->data.keys[i].values;
2863 regval_ctr_delvalue(ctr, "objectGUID");
2864 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2865 (char *) &guid, sizeof(struct uuid));
2868 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2869 NT_PRINTER_INFO_LEVEL *printer)
2873 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2874 char *srv_dn_utf8, **srv_cn_utf8;
2877 const char *attrs[] = {"objectGUID", NULL};
2879 WERROR win_rc = WERR_OK;
2881 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2883 /* figure out where to publish */
2884 ads_find_machine_acct(ads, &res, global_myname());
2886 /* We use ldap_get_dn here as we need the answer
2887 * in utf8 to call ldap_explode_dn(). JRA. */
2889 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2892 return WERR_SERVER_UNAVAILABLE;
2894 ads_msgfree(ads, res);
2895 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2897 ldap_memfree(srv_dn_utf8);
2899 return WERR_SERVER_UNAVAILABLE;
2901 /* Now convert to CH_UNIX. */
2902 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2903 ldap_memfree(srv_dn_utf8);
2904 ldap_memfree(srv_cn_utf8);
2906 return WERR_SERVER_UNAVAILABLE;
2908 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2909 ldap_memfree(srv_dn_utf8);
2910 ldap_memfree(srv_cn_utf8);
2913 return WERR_SERVER_UNAVAILABLE;
2916 ldap_memfree(srv_dn_utf8);
2917 ldap_memfree(srv_cn_utf8);
2919 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2920 printer->info_2->sharename, srv_dn);
2923 SAFE_FREE(srv_cn_0);
2925 /* build the ads mods */
2926 ctx = talloc_init("nt_printer_publish_ads");
2927 mods = ads_init_mods(ctx);
2929 get_local_printer_publishing_data(ctx, &mods,
2930 &printer->info_2->data);
2931 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2932 printer->info_2->sharename);
2935 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2936 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2937 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2939 if (!ADS_ERR_OK(ads_rc))
2940 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2942 talloc_destroy(ctx);
2944 /* retreive the guid and store it locally */
2945 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2947 ads_pull_guid(ads, res, &guid);
2948 ads_msgfree(ads, res);
2949 store_printer_guid(printer->info_2, guid);
2950 win_rc = mod_a_printer(printer, 2);
2957 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2958 NT_PRINTER_INFO_LEVEL *printer)
2962 char *prt_dn = NULL;
2964 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2966 /* remove the printer from the directory */
2967 ads_rc = ads_find_printer_on_server(ads, &res,
2968 printer->info_2->sharename, global_myname());
2970 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2971 prt_dn = ads_get_dn(ads, res);
2972 ads_rc = ads_del_dn(ads, prt_dn);
2973 ads_memfree(ads, prt_dn);
2976 ads_msgfree(ads, res);
2980 /****************************************************************************
2981 * Publish a printer in the directory
2983 * @param snum describing printer service
2984 * @return WERROR indicating status of publishing
2985 ***************************************************************************/
2987 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2990 ADS_STRUCT *ads = NULL;
2991 NT_PRINTER_INFO_LEVEL *printer = NULL;
2994 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2995 if (!W_ERROR_IS_OK(win_rc))
2999 case SPOOL_DS_PUBLISH:
3000 case SPOOL_DS_UPDATE:
3001 /* set the DsSpooler info and attributes */
3002 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3003 win_rc = WERR_NOMEM;
3007 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3009 case SPOOL_DS_UNPUBLISH:
3010 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3013 win_rc = WERR_NOT_SUPPORTED;
3017 win_rc = mod_a_printer(printer, 2);
3018 if (!W_ERROR_IS_OK(win_rc)) {
3019 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3023 ads = ads_init(NULL, NULL, NULL);
3025 DEBUG(3, ("ads_init() failed\n"));
3026 win_rc = WERR_SERVER_UNAVAILABLE;
3029 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3030 SAFE_FREE(ads->auth.password);
3031 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3034 /* ads_connect() will find the DC for us */
3035 ads_rc = ads_connect(ads);
3036 if (!ADS_ERR_OK(ads_rc)) {
3037 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3038 win_rc = WERR_ACCESS_DENIED;
3043 case SPOOL_DS_PUBLISH:
3044 case SPOOL_DS_UPDATE:
3045 win_rc = nt_printer_publish_ads(ads, printer);
3047 case SPOOL_DS_UNPUBLISH:
3048 win_rc = nt_printer_unpublish_ads(ads, printer);
3053 free_a_printer(&printer, 2);
3058 WERROR check_published_printers(void)
3061 ADS_STRUCT *ads = NULL;
3063 int n_services = lp_numservices();
3064 NT_PRINTER_INFO_LEVEL *printer = NULL;
3066 ads = ads_init(NULL, NULL, NULL);
3068 DEBUG(3, ("ads_init() failed\n"));
3069 return WERR_SERVER_UNAVAILABLE;
3071 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3072 SAFE_FREE(ads->auth.password);
3073 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3076 /* ads_connect() will find the DC for us */
3077 ads_rc = ads_connect(ads);
3078 if (!ADS_ERR_OK(ads_rc)) {
3079 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3081 return WERR_ACCESS_DENIED;
3084 for (snum = 0; snum < n_services; snum++) {
3085 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3088 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3089 lp_servicename(snum))) &&
3090 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3091 nt_printer_publish_ads(ads, printer);
3093 free_a_printer(&printer, 2);
3100 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3103 NT_PRINTER_INFO_LEVEL *printer = NULL;
3105 REGISTRY_VALUE *guid_val;
3109 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3111 if (!W_ERROR_IS_OK(win_rc) ||
3112 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3113 ((i = lookup_printerkey(&printer->info_2->data,
3114 SPOOL_DSSPOOLER_KEY)) < 0) ||
3115 !(ctr = &printer->info_2->data.keys[i].values) ||
3116 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
3117 free_a_printer(&printer, 2);
3121 /* fetching printer guids really ought to be a separate function.. */
3122 if (guid && regval_size(guid_val) == sizeof(struct uuid))
3123 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
3125 free_a_printer(&printer, 2);
3129 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3134 WERROR check_published_printers(void)
3139 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3144 #endif /* HAVE_ADS */
3146 /****************************************************************************
3147 ***************************************************************************/
3149 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3151 NT_PRINTER_DATA *data;
3153 int removed_keys = 0;
3157 empty_slot = data->num_keys;
3160 return WERR_INVALID_PARAM;
3162 /* remove all keys */
3164 if ( !strlen(key) ) {
3165 for ( i=0; i<data->num_keys; i++ ) {
3166 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3167 data->keys[i].name));
3169 SAFE_FREE( data->keys[i].name );
3170 regval_ctr_destroy( &data->keys[i].values );
3173 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3176 SAFE_FREE( data->keys );
3177 ZERO_STRUCTP( data );
3182 /* remove a specific key (and all subkeys) */
3184 for ( i=0; i<data->num_keys; i++ ) {
3185 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3186 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3187 data->keys[i].name));
3189 SAFE_FREE( data->keys[i].name );
3190 regval_ctr_destroy( &data->keys[i].values );
3192 /* mark the slot as empty */
3194 ZERO_STRUCTP( &data->keys[i] );
3198 /* find the first empty slot */
3200 for ( i=0; i<data->num_keys; i++ ) {
3201 if ( !data->keys[i].name ) {
3208 if ( i == data->num_keys )
3209 /* nothing was removed */
3210 return WERR_INVALID_PARAM;
3212 /* move everything down */
3214 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3215 if ( data->keys[i].name ) {
3216 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3217 ZERO_STRUCTP( &data->keys[i] );
3225 data->num_keys -= removed_keys;
3227 /* sanity check to see if anything is left */
3229 if ( !data->num_keys ) {
3230 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3232 SAFE_FREE( data->keys );
3233 ZERO_STRUCTP( data );
3239 /****************************************************************************
3240 ***************************************************************************/
3242 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3244 WERROR result = WERR_OK;
3247 /* we must have names on non-zero length */
3249 if ( !key || !*key|| !value || !*value )
3250 return WERR_INVALID_NAME;
3252 /* find the printer key first */
3254 key_index = lookup_printerkey( &p2->data, key );
3255 if ( key_index == -1 )
3258 /* make sure the value exists so we can return the correct error code */
3260 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3261 return WERR_BADFILE;
3263 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3265 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3271 /****************************************************************************
3272 ***************************************************************************/
3274 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3275 uint32 type, uint8 *data, int real_len )
3277 WERROR result = WERR_OK;
3280 /* we must have names on non-zero length */
3282 if ( !key || !*key|| !value || !*value )
3283 return WERR_INVALID_NAME;
3285 /* find the printer key first */
3287 key_index = lookup_printerkey( &p2->data, key );
3288 if ( key_index == -1 )
3289 key_index = add_new_printer_key( &p2->data, key );
3291 if ( key_index == -1 )
3294 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3295 type, (const char *)data, real_len );
3297 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3298 key, value, type, real_len ));
3303 /****************************************************************************
3304 ***************************************************************************/
3306 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3310 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3313 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3316 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3319 /****************************************************************************
3320 Unpack a list of registry values frem the TDB
3321 ***************************************************************************/
3323 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3327 pstring string, valuename, keyname;
3331 REGISTRY_VALUE *regval_p;
3334 /* add the "PrinterDriverData" key first for performance reasons */
3336 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3338 /* loop and unpack the rest of the registry values */
3342 /* check to see if there are any more registry values */
3345 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3349 /* unpack the next regval */
3351 len += tdb_unpack(buf+len, buflen-len, "fdB",
3357 /* lookup for subkey names which have a type of REG_NONE */
3358 /* there's no data with this entry */
3360 if ( type == REG_NONE ) {
3361 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3362 add_new_printer_key( printer_data, string );
3367 * break of the keyname from the value name.
3368 * Valuenames can have embedded '\'s so be careful.
3369 * only support one level of keys. See the
3370 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3374 str = strchr_m( string, '\\');
3376 /* Put in "PrinterDriverData" is no key specified */
3379 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3380 pstrcpy( valuename, string );
3384 pstrcpy( keyname, string );
3385 pstrcpy( valuename, str+1 );
3388 /* see if we need a new key */
3390 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3391 key_index = add_new_printer_key( printer_data, keyname );
3393 if ( key_index == -1 ) {
3394 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3399 /* add the new value */
3401 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3403 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3405 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3411 /****************************************************************************
3412 ***************************************************************************/
3414 static void map_to_os2_driver(fstring drivername)
3416 static BOOL initialised=False;
3417 static fstring last_from,last_to;
3418 char *mapfile = lp_os2_driver_map();
3419 char **lines = NULL;
3423 if (!strlen(drivername))
3430 *last_from = *last_to = 0;
3434 if (strequal(drivername,last_from)) {
3435 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3436 fstrcpy(drivername,last_to);
3440 lines = file_lines_load(mapfile, &numlines);
3441 if (numlines == 0) {
3442 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3446 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3448 for( i = 0; i < numlines; i++) {
3449 char *nt_name = lines[i];
3450 char *os2_name = strchr(nt_name,'=');
3457 while (isspace(*nt_name))
3460 if (!*nt_name || strchr("#;",*nt_name))
3464 int l = strlen(nt_name);
3465 while (l && isspace(nt_name[l-1])) {
3471 while (isspace(*os2_name))
3475 int l = strlen(os2_name);
3476 while (l && isspace(os2_name[l-1])) {
3482 if (strequal(nt_name,drivername)) {
3483 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3484 fstrcpy(last_from,drivername);
3485 fstrcpy(last_to,os2_name);
3486 fstrcpy(drivername,os2_name);
3487 file_lines_free(lines);
3492 file_lines_free(lines);
3495 /****************************************************************************
3496 Get a default printer info 2 struct.
3497 ****************************************************************************/
3498 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3501 NT_PRINTER_INFO_LEVEL_2 info;
3505 snum = lp_servicenumber(sharename);
3507 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3508 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3509 servername, sharename);
3510 fstrcpy(info.sharename, sharename);
3511 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3513 /* by setting the driver name to an empty string, a local NT admin
3514 can now run the **local** APW to install a local printer driver
3515 for a Samba shared printer in 2.2. Without this, drivers **must** be
3516 installed on the Samba server for NT clients --jerry */
3517 #if 0 /* JERRY --do not uncomment-- */
3518 if (!*info.drivername)
3519 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3523 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3525 pstrcpy(info.comment, "");
3526 fstrcpy(info.printprocessor, "winprint");
3527 fstrcpy(info.datatype, "RAW");
3529 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3531 info.starttime = 0; /* Minutes since 12:00am GMT */
3532 info.untiltime = 0; /* Minutes since 12:00am GMT */
3534 info.default_priority = 1;
3535 info.setuptime = (uint32)time(NULL);
3538 * I changed this as I think it is better to have a generic
3539 * DEVMODE than to crash Win2k explorer.exe --jerry
3540 * See the HP Deskjet 990c Win2k drivers for an example.
3542 * However the default devmode appears to cause problems
3543 * with the HP CLJ 8500 PCL driver. Hence the addition of
3544 * the "default devmode" parameter --jerry 22/01/2002
3547 if (lp_default_devmode(snum)) {
3548 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3552 info.devmode = NULL;
3555 /* This will get the current RPC talloc context, but we should be
3556 passing this as a parameter... fixme... JRA ! */
3558 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3561 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3563 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3571 free_nt_devicemode(&info.devmode);
3572 return WERR_ACCESS_DENIED;
3575 /****************************************************************************
3576 ****************************************************************************/
3577 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3580 NT_PRINTER_INFO_LEVEL_2 info;
3582 int snum = lp_servicenumber(sharename);
3583 TDB_DATA kbuf, dbuf;
3584 fstring printername;
3585 char adevice[MAXDEVICENAME];
3586 fstring norm_sharename;
3590 /* normalize case */
3591 fstrcpy( norm_sharename, sharename );
3592 strlower_m( norm_sharename );
3594 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, norm_sharename);
3597 kbuf.dsize = strlen(key)+1;
3599 dbuf = tdb_fetch(tdb_printers, kbuf);
3601 return get_a_printer_2_default(info_ptr, servername, norm_sharename);
3603 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3606 &info.default_priority,
3623 info.printprocessor,
3627 /* Samba has to have shared raw drivers. */
3628 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3629 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3631 /* Restore the stripped strings. */
3632 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3634 if ( lp_force_printername(snum) )
3635 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, norm_sharename );
3637 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3639 fstrcpy(info.printername, printername);
3641 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3644 * Some client drivers freak out if there is a NULL devmode
3645 * (probably the driver is not checking before accessing
3646 * the devmode pointer) --jerry
3648 * See comments in get_a_printer_2_default()
3651 if (lp_default_devmode(snum) && !info.devmode) {
3652 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3654 info.devmode = construct_nt_devicemode(printername);
3657 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3659 fstrcpy(info.devmode->devicename, adevice);
3662 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3664 /* This will get the current RPC talloc context, but we should be
3665 passing this as a parameter... fixme... JRA ! */
3667 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3669 /* Fix for OS/2 drivers. */
3671 if (get_remote_arch() == RA_OS2)
3672 map_to_os2_driver(info.drivername);
3674 SAFE_FREE(dbuf.dptr);
3675 *info_ptr=memdup(&info, sizeof(info));
3677 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3678 sharename, info.printername, info.drivername));
3683 /****************************************************************************
3684 Debugging function, dump at level 6 the struct in the logs.
3685 ****************************************************************************/
3686 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3689 NT_PRINTER_INFO_LEVEL_2 *info2;
3691 DEBUG(106,("Dumping printer at level [%d]\n", level));
3696 if (printer->info_2 == NULL)
3700 info2=printer->info_2;
3702 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3703 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3704 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3705 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3706 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3707 DEBUGADD(106,("status:[%d]\n", info2->status));
3708 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3709 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3710 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3711 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3712 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3714 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3715 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3716 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3717 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3718 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3719 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3720 DEBUGADD(106,("location:[%s]\n", info2->location));
3721 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3722 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3723 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3724 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3730 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3738 /****************************************************************************
3739 Update the changeid time.
3740 This is SO NASTY as some drivers need this to change, others need it
3741 static. This value will change every second, and I must hope that this
3742 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3744 ****************************************************************************/
3746 static uint32 rev_changeid(void)
3750 get_process_uptime(&tv);
3753 /* Return changeid as msec since spooler restart */
3754 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3757 * This setting seems to work well but is too untested
3758 * to replace the above calculation. Left in for experiementation
3759 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3761 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3765 /********************************************************************
3766 Send a message to all smbds about the printer that just changed
3767 ********************************************************************/
3769 static BOOL send_printer_mod_msg( char* printername )
3771 int len = strlen(printername);
3776 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3779 /* spam everyone that we just changed this printer */
3781 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3787 * The function below are the high level ones.
3788 * only those ones must be called from the spoolss code.
3792 /****************************************************************************
3793 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3794 ****************************************************************************/
3796 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3800 dump_a_printer(printer, level);
3803 * invalidate cache for all open handles to this printer.
3804 * cache for a given handle will be updated on the next
3808 invalidate_printer_hnd_cache( printer->info_2->sharename );
3809 send_printer_mod_msg( printer->info_2->sharename );
3815 * Update the changestamp. Emperical tests show that the
3816 * ChangeID is always updated,but c_setprinter is
3817 * global spooler variable (not per printer).
3820 /* ChangeID **must** be increasing over the lifetime
3821 of client's spoolss service in order for the
3822 client's cache to show updates */
3824 printer->info_2->changeid = rev_changeid();
3827 * Because one day someone will ask:
3828 * NT->NT An admin connection to a remote
3829 * printer show changes imeediately in
3830 * the properities dialog
3832 * A non-admin connection will only show the
3833 * changes after viewing the properites page
3834 * 2 times. Seems to be related to a
3835 * race condition in the client between the spooler
3836 * updating the local cache and the Explorer.exe GUI
3837 * actually displaying the properties.
3839 * This is fixed in Win2k. admin/non-admin
3840 * connections both display changes immediately.
3845 result=update_a_printer_2(printer->info_2);
3850 result=WERR_UNKNOWN_LEVEL;
3857 /****************************************************************************
3858 Initialize printer devmode & data with previously saved driver init values.
3859 ****************************************************************************/
3861 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3865 TDB_DATA kbuf, dbuf;
3866 NT_PRINTER_INFO_LEVEL_2 info;
3872 * Delete any printer data 'values' already set. When called for driver
3873 * replace, there will generally be some, but during an add printer, there
3874 * should not be any (if there are delete them).
3877 delete_all_printer_data( info_ptr, "" );
3879 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3882 kbuf.dsize = strlen(key)+1;
3884 dbuf = tdb_fetch(tdb_drivers, kbuf);
3887 * When changing to a driver that has no init info in the tdb, remove
3888 * the previous drivers init info and leave the new on blank.
3890 free_nt_devicemode(&info_ptr->devmode);
3895 * Get the saved DEVMODE..
3898 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3901 * The saved DEVMODE contains the devicename from the printer used during
3902 * the initialization save. Change it to reflect the new printer.
3905 if ( info.devmode ) {
3906 ZERO_STRUCT(info.devmode->devicename);
3907 fstrcpy(info.devmode->devicename, info_ptr->printername);
3911 * NT/2k does not change out the entire DeviceMode of a printer
3912 * when changing the driver. Only the driverextra, private, &
3913 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3915 * Later examination revealed that Windows NT/2k does reset the
3916 * the printer's device mode, bit **only** when you change a
3917 * property of the device mode such as the page orientation.
3922 /* Bind the saved DEVMODE to the new the printer */
3924 free_nt_devicemode(&info_ptr->devmode);
3925 info_ptr->devmode = info.devmode;
3927 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3928 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3930 /* Add the printer data 'values' to the new printer */
3932 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3935 SAFE_FREE(dbuf.dptr);
3940 /****************************************************************************
3941 Initialize printer devmode & data with previously saved driver init values.
3942 When a printer is created using AddPrinter, the drivername bound to the
3943 printer is used to lookup previously saved driver initialization info, which
3944 is bound to the new printer.
3945 ****************************************************************************/
3947 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3949 BOOL result = False;
3953 result = set_driver_init_2(printer->info_2);
3957 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3965 /****************************************************************************
3966 Delete driver init data stored for a specified driver
3967 ****************************************************************************/
3969 BOOL del_driver_init(char *drivername)
3974 if (!drivername || !*drivername) {
3975 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3979 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3982 kbuf.dsize = strlen(key)+1;
3984 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3986 return (tdb_delete(tdb_drivers, kbuf) == 0);
3989 /****************************************************************************
3990 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3991 in the tdb. Note: this is different from the driver entry and the printer
3992 entry. There should be a single driver init entry for each driver regardless
3993 of whether it was installed from NT or 2K. Technically, they should be
3994 different, but they work out to the same struct.
3995 ****************************************************************************/
3997 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4001 int buflen, len, ret;
4002 TDB_DATA kbuf, dbuf;
4009 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4011 len += pack_values( &info->data, buf+len, buflen-len );
4016 tb = (char *)SMB_REALLOC(buf, len);
4018 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4028 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4031 kbuf.dsize = strlen(key)+1;
4035 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
4039 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4043 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4044 info->sharename, info->drivername));
4049 /****************************************************************************
4050 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4051 ****************************************************************************/
4053 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4057 dump_a_printer(printer, level);
4061 result = update_driver_init_2(printer->info_2);
4071 /****************************************************************************
4072 Convert the printer data value, a REG_BINARY array, into an initialization
4073 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4074 got to keep the endians happy :).
4075 ****************************************************************************/
4077 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4079 BOOL result = False;
4083 ZERO_STRUCT(devmode);
4085 prs_init(&ps, 0, ctx, UNMARSHALL);
4086 ps.data_p = (char *)data;
4087 ps.buffer_size = data_len;
4089 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4090 result = convert_devicemode("", &devmode, &nt_devmode);
4092 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4097 /****************************************************************************
4098 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4100 1. Use the driver's config DLL to this UNC printername and:
4101 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4102 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4103 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4105 The last step triggers saving the "driver initialization" information for
4106 this printer into the tdb. Later, new printers that use this driver will
4107 have this initialization information bound to them. This simulates the
4108 driver initialization, as if it had run on the Samba server (as it would
4111 The Win32 client side code requirement sucks! But until we can run arbitrary
4112 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4114 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4115 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4116 about it and you will realize why. JRR 010720
4117 ****************************************************************************/
4119 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4121 WERROR status = WERR_OK;
4122 TALLOC_CTX *ctx = NULL;
4123 NT_DEVICEMODE *nt_devmode = NULL;
4124 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4127 * When the DEVMODE is already set on the printer, don't try to unpack it.
4129 DEBUG(8,("save_driver_init_2: Enter...\n"));
4131 if ( !printer->info_2->devmode && data_len ) {
4133 * Set devmode on printer info, so entire printer initialization can be
4137 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4140 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4141 status = WERR_NOMEM;
4145 ZERO_STRUCTP(nt_devmode);
4148 * The DEVMODE is held in the 'data' component of the param in raw binary.
4149 * Convert it to to a devmode structure
4151 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4152 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4153 status = WERR_INVALID_PARAM;
4157 printer->info_2->devmode = nt_devmode;
4161 * Pack up and add (or update) the DEVMODE and any current printer data to
4162 * a 'driver init' element in the tdb
4166 if ( update_driver_init(printer, 2) != 0 ) {
4167 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4168 status = WERR_NOMEM;
4173 * If driver initialization info was successfully saved, set the current
4174 * printer to match it. This allows initialization of the current printer
4175 * as well as the driver.
4177 status = mod_a_printer(printer, 2);
4178 if (!W_ERROR_IS_OK(status)) {
4179 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4180 printer->info_2->printername));
4184 talloc_destroy(ctx);
4185 free_nt_devicemode( &nt_devmode );
4187 printer->info_2->devmode = tmp_devmode;
4192 /****************************************************************************
4193 Update the driver init info (DEVMODE and specifics) for a printer
4194 ****************************************************************************/
4196 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4198 WERROR status = WERR_OK;
4202 status = save_driver_init_2( printer, data, data_len );
4205 status = WERR_UNKNOWN_LEVEL;
4212 /****************************************************************************
4213 Deep copy a NT_PRINTER_DATA
4214 ****************************************************************************/
4216 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
4218 int i, j, num_vals, new_key_index;
4219 REGVAL_CTR *src_key, *dst_key;
4222 return NT_STATUS_NO_MEMORY;
4224 for ( i=0; i<src->num_keys; i++ ) {
4226 /* create a new instance of the printerkey in the destination
4227 printer_data object */
4229 new_key_index = add_new_printer_key( dst, src->keys[i].name );
4230 dst_key = &dst->keys[new_key_index].values;
4232 src_key = &src->keys[i].values;
4233 num_vals = regval_ctr_numvals( src_key );
4235 /* dup the printer entire printer key */
4237 for ( j=0; j<num_vals; j++ ) {
4238 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4242 return NT_STATUS_OK;
4245 /****************************************************************************
4246 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4248 ****************************************************************************/
4250 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4252 NT_PRINTER_INFO_LEVEL_2 *copy;
4257 if ( !(copy = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2)) )
4260 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4262 /* malloc()'d members copied here */
4264 copy->devmode = dup_nt_devicemode( printer->devmode );
4266 ZERO_STRUCT( copy->data );
4267 copy_printer_data( ©->data, &printer->data );
4269 /* this is talloc()'d; very ugly that we have a structure that
4270 is half malloc()'d and half talloc()'d but that is the way
4271 that the PRINTER_INFO stuff is written right now. --jerry */
4273 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4278 /****************************************************************************
4279 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4281 Previously the code had a memory allocation problem because it always
4282 used the TALLOC_CTX from the Printer_entry*. This context lasts
4283 as a long as the original handle is open. So if the client made a lot
4284 of getprinter[data]() calls, the memory usage would climb. Now we use
4285 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4286 still use the Printer_entry->ctx for maintaining the cache copy though
4287 since that object must live as long as the handle by definition.
4290 ****************************************************************************/
4292 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4293 const char *sharename)
4296 NT_PRINTER_INFO_LEVEL *printer = NULL;
4301 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4305 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
4306 DEBUG(0,("get_a_printer: malloc fail.\n"));
4309 ZERO_STRUCTP(printer);
4312 fstrcpy( servername, print_hnd->servername );
4314 fstrcpy( servername, "%L" );
4315 standard_sub_basic( "", servername, sizeof(servername)-1 );
4319 * check for cache first. A Printer handle cannot changed
4320 * to another printer object so we only check that the printer
4321 * is actually for a printer and that the printer_info pointer
4325 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4326 && print_hnd->printer_info )
4328 /* get_talloc_ctx() works here because we need a short
4329 lived talloc context */
4331 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4333 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4339 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4341 *pp_printer = printer;
4347 /* no cache for this handle; see if we can match one from another handle.
4348 Make sure to use a short lived talloc ctx */
4351 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4353 /* fail to disk if we don't have it with any open handle */
4355 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4356 result = get_a_printer_2(&printer->info_2, servername, sharename );
4358 /* we have a new printer now. Save it with this handle */
4360 if ( W_ERROR_IS_OK(result) ) {
4361 dump_a_printer(printer, level);
4363 /* save a copy in cache */
4364 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4365 if ( !print_hnd->printer_info )
4366 print_hnd->printer_info = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL);
4368 if ( print_hnd->printer_info ) {
4369 /* make sure to use the handle's talloc ctx here since
4370 the printer_2 object must last until the handle is closed */
4372 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4374 /* don't fail the lookup just because the cache update failed */
4375 if ( !print_hnd->printer_info->info_2 )
4376 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4379 *pp_printer = printer;
4387 result=WERR_UNKNOWN_LEVEL;
4391 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4396 /****************************************************************************
4397 Deletes a NT_PRINTER_INFO_LEVEL struct.
4398 ****************************************************************************/
4400 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4403 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4405 DEBUG(104,("freeing a printer at level [%d]\n", level));
4407 if (printer == NULL)
4412 if (printer->info_2 != NULL) {
4413 free_nt_printer_info_level_2(&printer->info_2);
4424 SAFE_FREE(*pp_printer);
4428 /****************************************************************************
4429 ****************************************************************************/
4430 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4433 DEBUG(104,("adding a printer at level [%d]\n", level));
4434 dump_a_printer_driver(driver, level);
4438 result=add_a_printer_driver_3(driver.info_3);
4442 result=add_a_printer_driver_6(driver.info_6);
4452 /****************************************************************************
4453 ****************************************************************************/
4455 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4456 fstring drivername, const char *architecture, uint32 version)
4462 /* Sometime we just want any version of the driver */
4464 if ( version == DRIVER_ANY_VERSION ) {
4465 /* look for Win2k first and then for NT4 */
4466 result = get_a_printer_driver_3(&driver->info_3, drivername,
4469 if ( !W_ERROR_IS_OK(result) ) {
4470 result = get_a_printer_driver_3( &driver->info_3,
4471 drivername, architecture, 2 );
4474 result = get_a_printer_driver_3(&driver->info_3, drivername,
4475 architecture, version);
4484 if (W_ERROR_IS_OK(result))
4485 dump_a_printer_driver(*driver, level);
4490 /****************************************************************************
4491 ****************************************************************************/
4492 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4499 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4500 if (driver.info_3 != NULL)
4502 info3=driver.info_3;
4503 SAFE_FREE(info3->dependentfiles);
4504 ZERO_STRUCTP(info3);
4514 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4515 if (driver.info_6 != NULL) {
4516 info6=driver.info_6;
4517 SAFE_FREE(info6->dependentfiles);
4518 SAFE_FREE(info6->previousnames);
4519 ZERO_STRUCTP(info6);
4535 /****************************************************************************
4536 Determine whether or not a particular driver is currently assigned
4538 ****************************************************************************/
4540 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4543 int n_services = lp_numservices();
4544 NT_PRINTER_INFO_LEVEL *printer = NULL;
4545 BOOL in_use = False;
4550 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4552 /* loop through the printers.tdb and check for the drivername */
4554 for (snum=0; snum<n_services && !in_use; snum++) {
4555 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4558 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4561 if ( strequal(info_3->name, printer->info_2->drivername) )
4564 free_a_printer( &printer, 2 );
4567 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4570 NT_PRINTER_DRIVER_INFO_LEVEL d;
4573 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4575 /* we can still remove the driver if there is one of
4576 "Windows NT x86" version 2 or 3 left */
4578 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4579 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4582 switch ( info_3->cversion ) {
4584 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4587 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4590 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4592 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4597 /* now check the error code */
4599 if ( W_ERROR_IS_OK(werr) ) {
4600 /* it's ok to remove the driver, we have other architctures left */
4602 free_a_printer_driver( d, 3 );
4606 /* report that the driver is not in use by default */
4612 /**********************************************************************
4613 Check to see if a ogiven file is in use by *info
4614 *********************************************************************/
4616 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4623 if ( strequal(file, info->driverpath) )
4626 if ( strequal(file, info->datafile) )
4629 if ( strequal(file, info->configfile) )
4632 if ( strequal(file, info->helpfile) )
4635 /* see of there are any dependent files to examine */
4637 if ( !info->dependentfiles )
4640 while ( *info->dependentfiles[i] ) {
4641 if ( strequal(file, info->dependentfiles[i]) )
4650 /**********************************************************************
4651 Utility function to remove the dependent file pointed to by the
4652 input parameter from the list
4653 *********************************************************************/
4655 static void trim_dependent_file( fstring files[], int idx )
4658 /* bump everything down a slot */
4660 while( *files[idx+1] ) {
4661 fstrcpy( files[idx], files[idx+1] );
4670 /**********************************************************************
4671 Check if any of the files used by src are also used by drv
4672 *********************************************************************/
4674 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4675 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4677 BOOL in_use = False;
4683 /* check each file. Remove it from the src structure if it overlaps */
4685 if ( drv_file_in_use(src->driverpath, drv) ) {
4687 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4688 fstrcpy( src->driverpath, "" );
4691 if ( drv_file_in_use(src->datafile, drv) ) {
4693 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4694 fstrcpy( src->datafile, "" );
4697 if ( drv_file_in_use(src->configfile, drv) ) {
4699 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4700 fstrcpy( src->configfile, "" );
4703 if ( drv_file_in_use(src->helpfile, drv) ) {
4705 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4706 fstrcpy( src->helpfile, "" );
4709 /* are there any dependentfiles to examine? */
4711 if ( !src->dependentfiles )
4714 while ( *src->dependentfiles[i] ) {
4715 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4717 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4718 trim_dependent_file( src->dependentfiles, i );
4726 /****************************************************************************
4727 Determine whether or not a particular driver files are currently being
4728 used by any other driver.
4730 Return value is True if any files were in use by other drivers
4731 and False otherwise.
4733 Upon return, *info has been modified to only contain the driver files
4734 which are not in use
4735 ****************************************************************************/
4737 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4742 fstring *list = NULL;
4743 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4748 version = info->cversion;
4750 /* loop over all driver versions */
4752 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4754 /* get the list of drivers */
4757 ndrivers = get_ntdrivers(&list, info->environment, version);
4759 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4760 ndrivers, info->environment, version));
4762 /* check each driver for overlap in files */
4764 for (i=0; i<ndrivers; i++) {
4765 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4767 ZERO_STRUCT(driver);
4769 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4774 /* check if d2 uses any files from d1 */
4775 /* only if this is a different driver than the one being deleted */
4777 if ( !strequal(info->name, driver.info_3->name) ) {
4778 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4779 free_a_printer_driver(driver, 3);
4785 free_a_printer_driver(driver, 3);
4790 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4792 driver.info_3 = info;
4794 if ( DEBUGLEVEL >= 20 )
4795 dump_a_printer_driver( driver, 3 );
4800 /****************************************************************************
4801 Actually delete the driver files. Make sure that
4802 printer_driver_files_in_use() return False before calling
4804 ****************************************************************************/
4806 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4810 connection_struct *conn;
4820 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4823 * Connect to the print$ share under the same account as the
4824 * user connected to the rpc pipe. Note we must be root to
4828 null_pw = data_blob( NULL, 0 );
4829 fstrcpy(res_type, "A:");
4831 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4835 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4839 /* Save who we are - we are temporarily becoming the connection user. */
4841 if ( !become_user(conn, conn->vuid) ) {
4842 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4846 /* now delete the files; must strip the '\print$' string from
4849 if ( *info_3->driverpath ) {
4850 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4851 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4852 DEBUG(10,("deleting driverfile [%s]\n", s));
4853 unlink_internals(conn, 0, s);
4857 if ( *info_3->configfile ) {
4858 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4859 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4860 DEBUG(10,("deleting configfile [%s]\n", s));
4861 unlink_internals(conn, 0, s);
4865 if ( *info_3->datafile ) {
4866 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4867 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4868 DEBUG(10,("deleting datafile [%s]\n", s));
4869 unlink_internals(conn, 0, s);
4873 if ( *info_3->helpfile ) {
4874 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4875 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4876 DEBUG(10,("deleting helpfile [%s]\n", s));
4877 unlink_internals(conn, 0, s);
4881 /* check if we are done removing files */
4883 if ( info_3->dependentfiles ) {
4884 while ( *info_3->dependentfiles[i] ) {
4887 /* bypass the "\print$" portion of the path */
4889 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4890 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4891 DEBUG(10,("deleting dependent file [%s]\n", file));
4892 unlink_internals(conn, 0, file );
4904 /****************************************************************************
4905 Remove a printer driver from the TDB. This assumes that the the driver was
4906 previously looked up.
4907 ***************************************************************************/
4909 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4910 uint32 version, BOOL delete_files )
4914 TDB_DATA kbuf, dbuf;
4915 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4917 /* delete the tdb data first */
4919 arch = get_short_archi(info_3->environment);
4920 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4921 arch, version, info_3->name);
4923 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4924 key, delete_files ? "TRUE" : "FALSE" ));
4926 ctr.info_3 = info_3;
4927 dump_a_printer_driver( ctr, 3 );
4930 kbuf.dsize=strlen(key)+1;
4932 /* check if the driver actually exists for this environment */
4934 dbuf = tdb_fetch( tdb_drivers, kbuf );
4936 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4937 return WERR_UNKNOWN_PRINTER_DRIVER;
4940 SAFE_FREE( dbuf.dptr );
4942 /* ok... the driver exists so the delete should return success */
4944 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4945 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4946 return WERR_ACCESS_DENIED;
4950 * now delete any associated files if delete_files == True
4951 * even if this part failes, we return succes because the
4952 * driver doesn not exist any more
4956 delete_driver_files( info_3, user );
4959 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4964 /****************************************************************************
4965 Store a security desc for a printer.
4966 ****************************************************************************/
4968 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
4970 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4971 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4973 TALLOC_CTX *mem_ctx = NULL;
4976 fstring norm_sharename;
4978 fstrcpy( norm_sharename, sharename );
4979 strlower_m( norm_sharename );
4981 mem_ctx = talloc_init("nt_printing_setsec");
4982 if (mem_ctx == NULL)
4985 /* The old owner and group sids of the security descriptor are not
4986 present when new ACEs are added or removed by changing printer
4987 permissions through NT. If they are NULL in the new security
4988 descriptor then copy them over from the old one. */
4990 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4991 DOM_SID *owner_sid, *group_sid;
4992 SEC_ACL *dacl, *sacl;
4993 SEC_DESC *psd = NULL;
4996 nt_printing_getsec(mem_ctx, norm_sharename, &old_secdesc_ctr);
4998 /* Pick out correct owner and group sids */
5000 owner_sid = secdesc_ctr->sec->owner_sid ?
5001 secdesc_ctr->sec->owner_sid :
5002 old_secdesc_ctr->sec->owner_sid;
5004 group_sid = secdesc_ctr->sec->grp_sid ?
5005 secdesc_ctr->sec->grp_sid :
5006 old_secdesc_ctr->sec->grp_sid;
5008 dacl = secdesc_ctr->sec->dacl ?
5009 secdesc_ctr->sec->dacl :
5010 old_secdesc_ctr->sec->dacl;
5012 sacl = secdesc_ctr->sec->sacl ?
5013 secdesc_ctr->sec->sacl :
5014 old_secdesc_ctr->sec->sacl;
5016 /* Make a deep copy of the security descriptor */
5018 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
5019 owner_sid, group_sid,
5024 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5027 if (!new_secdesc_ctr) {
5028 new_secdesc_ctr = secdesc_ctr;
5031 /* Store the security descriptor in a tdb */
5033 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
5034 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5036 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5038 status = WERR_BADFUNC;
5042 slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename);
5044 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
5047 DEBUG(1,("Failed to store secdesc for %s\n", norm_sharename));
5048 status = WERR_BADFUNC;
5051 /* Free malloc'ed memory */
5057 talloc_destroy(mem_ctx);
5061 /****************************************************************************
5062 Construct a default security descriptor buffer for a printer.
5063 ****************************************************************************/
5065 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5067 SEC_ACE ace[5]; /* max number of ace entries */
5070 SEC_ACL *psa = NULL;
5071 SEC_DESC_BUF *sdb = NULL;
5072 SEC_DESC *psd = NULL;
5076 /* Create an ACE where Everyone is allowed to print */
5078 init_sec_access(&sa, PRINTER_ACE_PRINT);
5079 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5080 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5082 /* Add the domain admins group if we are a DC */
5085 DOM_SID domadmins_sid;
5087 sid_copy(&domadmins_sid, get_global_sam_sid());
5088 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5090 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5091 init_sec_ace(&ace[i++], &domadmins_sid,
5092 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5093 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5094 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5095 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5097 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5098 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5100 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5101 init_sec_ace(&ace[i++], &adm_sid,
5102 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5103 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5104 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5105 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5108 /* add BUILTIN\Administrators as FULL CONTROL */
5110 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5111 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5112 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5113 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5114 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5115 SEC_ACE_TYPE_ACCESS_ALLOWED,
5116 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5118 /* Make the security descriptor owned by the BUILTIN\Administrators */
5120 /* The ACL revision number in rpc_secdesc.h differs from the one
5121 created by NT when setting ACE entries in printer
5122 descriptors. NT4 complains about the property being edited by a
5125 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5126 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5127 &global_sid_Builtin_Administrators,
5128 &global_sid_Builtin_Administrators,
5129 NULL, psa, &sd_size);
5133 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5137 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5139 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5140 (unsigned int)sd_size));
5145 /****************************************************************************
5146 Get a security desc for a printer.
5147 ****************************************************************************/
5149 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5154 fstring norm_sharename;
5156 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5157 sharename = temp + 1;
5160 /* Fetch security descriptor from tdb */
5162 fstrcpy( norm_sharename, sharename );
5163 strlower_m( norm_sharename );
5165 slprintf(key, sizeof(key)-1, "SECDESC/%s", norm_sharename);
5167 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
5168 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5170 DEBUG(4,("using default secdesc for %s\n", norm_sharename));
5172 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5176 /* Save default security descriptor for later */
5178 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
5179 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5181 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
5182 tdb_prs_store(tdb_printers, key, &ps);
5189 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5190 this security descriptor has been created when winbindd was
5191 down. Take ownership of security descriptor. */
5193 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
5196 /* Change sd owner to workgroup administrator */
5198 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5199 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5200 SEC_DESC *psd = NULL;
5205 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5207 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
5209 (*secdesc_ctr)->sec->grp_sid,
5210 (*secdesc_ctr)->sec->sacl,
5211 (*secdesc_ctr)->sec->dacl,
5214 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5216 /* Swap with other one */
5218 *secdesc_ctr = new_secdesc_ctr;
5222 nt_printing_setsec(norm_sharename, *secdesc_ctr);
5226 if (DEBUGLEVEL >= 10) {
5227 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
5230 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5231 norm_sharename, the_acl->num_aces));
5233 for (i = 0; i < the_acl->num_aces; i++) {
5236 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5238 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5239 the_acl->ace[i].type, the_acl->ace[i].flags,
5240 the_acl->ace[i].info.mask));
5250 1: level not implemented
5251 2: file doesn't exist
5252 3: can't allocate memory
5253 4: can't free memory
5254 5: non existant struct
5258 A printer and a printer driver are 2 different things.
5259 NT manages them separatelly, Samba does the same.
5260 Why ? Simply because it's easier and it makes sense !
5262 Now explanation: You have 3 printers behind your samba server,
5263 2 of them are the same make and model (laser A and B). But laser B
5264 has an 3000 sheet feeder and laser A doesn't such an option.
5265 Your third printer is an old dot-matrix model for the accounting :-).
5267 If the /usr/local/samba/lib directory (default dir), you will have
5268 5 files to describe all of this.
5270 3 files for the printers (1 by printer):
5273 NTprinter_accounting
5274 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5275 NTdriver_printer model X
5276 NTdriver_printer model Y
5278 jfm: I should use this comment for the text file to explain
5279 same thing for the forms BTW.
5280 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5284 /* Convert generic access rights to printer object specific access rights.
5285 It turns out that NT4 security descriptors use generic access rights and
5286 NT5 the object specific ones. */
5288 void map_printer_permissions(SEC_DESC *sd)
5292 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5293 se_map_generic(&sd->dacl->ace[i].info.mask,
5294 &printer_generic_mapping);
5298 /****************************************************************************
5299 Check a user has permissions to perform the given operation. We use the
5300 permission constants defined in include/rpc_spoolss.h to check the various
5301 actions we perform when checking printer access.
5303 PRINTER_ACCESS_ADMINISTER:
5304 print_queue_pause, print_queue_resume, update_printer_sec,
5305 update_printer, spoolss_addprinterex_level_2,
5306 _spoolss_setprinterdata
5311 JOB_ACCESS_ADMINISTER:
5312 print_job_delete, print_job_pause, print_job_resume,
5315 Try access control in the following order (for performance reasons):
5316 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5317 2) check security descriptor (bit comparisons in memory)
5318 3) "printer admins" (may result in numerous calls to winbind)
5320 ****************************************************************************/
5321 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5323 SEC_DESC_BUF *secdesc = NULL;
5324 uint32 access_granted;
5328 TALLOC_CTX *mem_ctx = NULL;
5329 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5331 /* If user is NULL then use the current_user structure */
5334 user = ¤t_user;
5336 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5338 if ( user->uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5342 /* Get printer name */
5344 pname = PRINTERNAME(snum);
5346 if (!pname || !*pname) {
5351 /* Get printer security descriptor */
5353 if(!(mem_ctx = talloc_init("print_access_check"))) {
5358 nt_printing_getsec(mem_ctx, pname, &secdesc);
5360 if (access_type == JOB_ACCESS_ADMINISTER) {
5361 SEC_DESC_BUF *parent_secdesc = secdesc;
5363 /* Create a child security descriptor to check permissions
5364 against. This is because print jobs are child objects
5365 objects of a printer. */
5367 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5369 /* Now this is the bit that really confuses me. The access
5370 type needs to be changed from JOB_ACCESS_ADMINISTER to
5371 PRINTER_ACCESS_ADMINISTER for this to work. Something
5372 to do with the child (job) object becoming like a
5375 access_type = PRINTER_ACCESS_ADMINISTER;
5380 map_printer_permissions(secdesc->sec);
5382 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5383 &access_granted, &status);
5385 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5387 /* see if we need to try the printer admin list */
5389 if ( access_granted == 0 ) {
5390 if ( user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups) )
5394 talloc_destroy(mem_ctx);
5402 /****************************************************************************
5403 Check the time parameters allow a print operation.
5404 *****************************************************************************/
5406 BOOL print_time_access_check(int snum)
5408 NT_PRINTER_INFO_LEVEL *printer = NULL;
5410 time_t now = time(NULL);
5414 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5417 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5421 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5423 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5426 free_a_printer(&printer, 2);
5434 /****************************************************************************
5435 Fill in the servername sent in the _spoolss_open_printer_ex() call
5436 ****************************************************************************/
5437 char* get_server_name( Printer_entry *printer )
5439 return printer->servername;