2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern struct current_user current_user
;
27 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
28 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
29 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping
= {
53 STANDARD_MAPPING printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping
= {
69 STANDARD_MAPPING printserver_std_mapping
= {
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms
[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
202 const char *long_archi
;
203 const char *short_archi
;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
212 #define SPL_ARCH_IA64 "IA64"
213 #define SPL_ARCH_X64 "x64"
215 static const struct table_node archi_table
[]= {
217 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
218 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
219 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
220 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
221 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
222 {"Windows IA64", SPL_ARCH_IA64
, 3 },
223 {"Windows x64", SPL_ARCH_X64
, 3 },
228 /****************************************************************************
229 generate a new TDB_DATA key for storing a printer
230 ****************************************************************************/
232 static TDB_DATA
make_printer_tdbkey( const char *sharename
)
235 static pstring keystr
;
238 fstrcpy( share
, sharename
);
241 pstr_sprintf( keystr
, "%s%s", PRINTERS_PREFIX
, share
);
244 key
.dsize
= strlen(keystr
)+1;
249 /****************************************************************************
250 generate a new TDB_DATA key for storing a printer security descriptor
251 ****************************************************************************/
253 static char* make_printers_secdesc_tdbkey( const char* sharename
)
256 static pstring keystr
;
258 fstrcpy( share
, sharename
);
261 pstr_sprintf( keystr
, "%s%s", SECDESC_PREFIX
, share
);
266 /****************************************************************************
267 ****************************************************************************/
269 static BOOL
upgrade_to_version_3(void)
271 TDB_DATA kbuf
, newkey
, dbuf
;
273 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
275 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
276 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
278 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
280 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
281 DEBUG(0,("upgrade_to_version_3:moving form\n"));
282 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
283 SAFE_FREE(dbuf
.dptr
);
284 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
287 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
288 SAFE_FREE(dbuf
.dptr
);
289 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
294 if (strncmp(kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
295 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
296 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
297 SAFE_FREE(dbuf
.dptr
);
298 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
301 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
302 SAFE_FREE(dbuf
.dptr
);
303 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
308 if (strncmp(kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
309 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
310 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
311 SAFE_FREE(dbuf
.dptr
);
312 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
315 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
316 SAFE_FREE(dbuf
.dptr
);
317 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
322 SAFE_FREE(dbuf
.dptr
);
328 /*******************************************************************
329 Fix an issue with security descriptors. Printer sec_desc must
330 use more than the generic bits that were previously used
331 in <= 3.0.14a. They must also have a owner and group SID assigned.
332 Otherwise, any printers than have been migrated to a Windows
333 host using printmig.exe will not be accessible.
334 *******************************************************************/
336 static int sec_desc_upg_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
337 TDB_DATA data
, void *state
)
340 SEC_DESC_BUF
*sd_orig
= NULL
;
341 SEC_DESC_BUF
*sd_new
, *sd_store
;
342 SEC_DESC
*sec
, *new_sec
;
343 TALLOC_CTX
*ctx
= state
;
349 if (!data
.dptr
|| data
.dsize
== 0)
352 if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 )
355 /* upgrade the security descriptor */
359 prs_init( &ps
, 0, ctx
, UNMARSHALL
);
360 prs_give_memory( &ps
, data
.dptr
, data
.dsize
, True
);
362 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig
, &ps
, 1 ) ) {
363 /* delete bad entries */
364 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key
.dptr
));
365 tdb_delete( tdb_printers
, key
);
371 /* is this even valid? */
376 /* update access masks */
378 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
379 switch ( sec
->dacl
->ace
[i
].info
.mask
) {
380 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
381 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_PRINT
;
384 case GENERIC_ALL_ACCESS
:
385 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_FULL_CONTROL
;
388 case READ_CONTROL_ACCESS
:
389 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
391 default: /* no change */
396 /* create a new SEC_DESC with the appropriate owner and group SIDs */
398 string_to_sid(&sid
, "S-1-5-32-544" );
399 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
401 NULL
, NULL
, &size_new_sec
);
402 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
404 if ( !(sd_store
= sec_desc_merge( ctx
, sd_new
, sd_orig
)) ) {
405 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
411 sd_size
= sec_desc_size(sd_store
->sec
) + sizeof(SEC_DESC_BUF
);
412 prs_init(&ps
, sd_size
, ctx
, MARSHALL
);
414 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store
, &ps
, 1 ) ) {
415 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
419 data
.dptr
= prs_data_p( &ps
);
420 data
.dsize
= sd_size
;
422 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
426 /* 0 to continue and non-zero to stop traversal */
428 return (result
== -1);
431 /*******************************************************************
432 *******************************************************************/
434 static BOOL
upgrade_to_version_4(void)
439 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
441 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
444 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
446 talloc_destroy( ctx
);
448 return ( result
!= -1 );
451 /*******************************************************************
452 Fix an issue with security descriptors. Printer sec_desc must
453 use more than the generic bits that were previously used
454 in <= 3.0.14a. They must also have a owner and group SID assigned.
455 Otherwise, any printers than have been migrated to a Windows
456 host using printmig.exe will not be accessible.
457 *******************************************************************/
459 static int normalize_printers_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
460 TDB_DATA data
, void *state
)
464 if (!data
.dptr
|| data
.dsize
== 0)
467 /* upgrade printer records and security descriptors */
469 if ( strncmp( key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
470 new_key
= make_printer_tdbkey( key
.dptr
+strlen(PRINTERS_PREFIX
) );
472 else if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
473 new_key
.dptr
= make_printers_secdesc_tdbkey( key
.dptr
+strlen(SECDESC_PREFIX
) );
474 new_key
.dsize
= strlen( new_key
.dptr
) + 1;
477 /* ignore this record */
481 /* delete the original record and store under the normalized key */
483 if ( tdb_delete( the_tdb
, key
) != 0 ) {
484 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
489 if ( tdb_store( the_tdb
, new_key
, data
, TDB_REPLACE
) != 0 ) {
490 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
498 /*******************************************************************
499 *******************************************************************/
501 static BOOL
upgrade_to_version_5(void)
506 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
508 if ( !(ctx
= talloc_init( "upgrade_to_version_5" )) )
511 result
= tdb_traverse( tdb_printers
, normalize_printers_fn
, NULL
);
513 talloc_destroy( ctx
);
515 return ( result
!= -1 );
518 /****************************************************************************
519 Open the NT printing tdbs. Done once before fork().
520 ****************************************************************************/
522 BOOL
nt_printing_init(void)
524 const char *vstring
= "INFO/version";
528 if ( tdb_drivers
&& tdb_printers
&& tdb_forms
)
532 tdb_close(tdb_drivers
);
533 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
535 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
536 lock_path("ntdrivers.tdb"), strerror(errno
) ));
541 tdb_close(tdb_printers
);
542 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
544 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
545 lock_path("ntprinters.tdb"), strerror(errno
) ));
550 tdb_close(tdb_forms
);
551 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
553 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
554 lock_path("ntforms.tdb"), strerror(errno
) ));
558 /* handle a Samba upgrade */
560 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
562 DEBUG(10, ("Fresh database\n"));
563 tdb_store_int32( tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
564 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
567 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
569 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
570 if (!upgrade_to_version_3())
572 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
573 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
576 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
577 /* Written on a bigendian machine with old fetch_int code. Save as le. */
578 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
579 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
580 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
583 if (vers_id
== NTDRIVERS_DATABASE_VERSION_3
) {
584 if ( !upgrade_to_version_4() )
586 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_4
);
587 vers_id
= NTDRIVERS_DATABASE_VERSION_4
;
590 if (vers_id
== NTDRIVERS_DATABASE_VERSION_4
) {
591 if ( !upgrade_to_version_5() )
593 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
594 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
598 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
599 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id
));
604 update_c_setprinter(True
);
607 * register callback to handle updating printers as new
608 * drivers are installed
611 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
614 * register callback to handle updating printer data
615 * when a driver is initialized
618 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
620 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
622 * register callback to handle invalidating the printer cache
623 * between smbd processes.
626 message_register( MSG_PRINTER_MOD
, receive_printer_mod_msg
);
629 /* of course, none of the message callbacks matter if you don't
630 tell messages.c that you interested in receiving PRINT_GENERAL
631 msgs. This is done in claim_connection() */
634 if ( lp_security() == SEC_ADS
) {
635 win_rc
= check_published_printers();
636 if (!W_ERROR_IS_OK(win_rc
))
637 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
643 /*******************************************************************
644 Function to allow filename parsing "the old way".
645 ********************************************************************/
647 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
648 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
651 unix_clean_name(name
);
652 trim_string(name
,"/","/");
653 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
656 /*******************************************************************
657 tdb traversal function for counting printers.
658 ********************************************************************/
660 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
661 TDB_DATA data
, void *context
)
663 int *printer_count
= (int*)context
;
665 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
667 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
673 /*******************************************************************
674 Update the spooler global c_setprinter. This variable is initialized
675 when the parent smbd starts with the number of existing printers. It
676 is monotonically increased by the current number of printers *after*
677 each add or delete printer RPC. Only Microsoft knows why... JRR020119
678 ********************************************************************/
680 uint32
update_c_setprinter(BOOL initialize
)
683 int32 printer_count
= 0;
685 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
687 /* Traverse the tdb, counting the printers */
688 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
690 /* If initializing, set c_setprinter to current printers count
691 * otherwise, bump it by the current printer count
694 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
696 c_setprinter
= printer_count
;
698 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
699 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
701 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
703 return (uint32
)c_setprinter
;
706 /*******************************************************************
707 Get the spooler global c_setprinter, accounting for initialization.
708 ********************************************************************/
710 uint32
get_c_setprinter(void)
712 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
714 if (c_setprinter
== (int32
)-1)
715 c_setprinter
= update_c_setprinter(True
);
717 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
719 return (uint32
)c_setprinter
;
722 /****************************************************************************
723 Get builtin form struct list.
724 ****************************************************************************/
726 int get_builtin_ntforms(nt_forms_struct
**list
)
728 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
729 return sizeof(default_forms
) / sizeof(default_forms
[0]);
732 /****************************************************************************
733 get a builtin form struct
734 ****************************************************************************/
736 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
740 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
741 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
742 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
743 for (i
=0;i
<count
;i
++) {
744 if (strequal(form_name
,default_forms
[i
].name
)) {
745 DEBUGADD(6,("Found builtin form %s \n", form_name
));
746 memcpy(form
,&default_forms
[i
],sizeof(*form
));
754 /****************************************************************************
755 get a form struct list
756 ****************************************************************************/
757 int get_ntforms(nt_forms_struct
**list
)
759 TDB_DATA kbuf
, newkey
, dbuf
;
761 nt_forms_struct form
;
766 for (kbuf
= tdb_firstkey(tdb_forms
);
768 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
770 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
773 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
777 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
778 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
779 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
780 &form
.top
, &form
.right
, &form
.bottom
);
781 SAFE_FREE(dbuf
.dptr
);
782 if (ret
!= dbuf
.dsize
)
785 tl
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
787 DEBUG(0,("get_ntforms: Realloc fail.\n"));
799 /****************************************************************************
800 write a form struct list
801 ****************************************************************************/
802 int write_ntforms(nt_forms_struct
**list
, int number
)
809 for (i
=0;i
<number
;i
++) {
810 /* save index, so list is rebuilt in correct order */
811 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
812 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
813 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
815 if (len
> sizeof(buf
)) break;
816 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
817 kbuf
.dsize
= strlen(key
)+1;
821 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
827 /****************************************************************************
828 add a form struct at the end of the list
829 ****************************************************************************/
830 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
838 * NT tries to add forms even when
839 * they are already in the base
840 * only update the values if already present
845 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
846 for (n
=0; n
<*count
; n
++) {
847 if ( strequal((*list
)[n
].name
, form_name
) ) {
854 if((tl
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
855 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
859 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
863 (*list
)[n
].flag
=form
->flags
;
864 (*list
)[n
].width
=form
->size_x
;
865 (*list
)[n
].length
=form
->size_y
;
866 (*list
)[n
].left
=form
->left
;
867 (*list
)[n
].top
=form
->top
;
868 (*list
)[n
].right
=form
->right
;
869 (*list
)[n
].bottom
=form
->bottom
;
871 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
872 update
? "updated" : "added", form_name
));
877 /****************************************************************************
878 Delete a named form struct.
879 ****************************************************************************/
881 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
890 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
892 for (n
=0; n
<*count
; n
++) {
893 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
894 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
900 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
901 *ret
= WERR_INVALID_PARAM
;
905 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
906 kbuf
.dsize
= strlen(key
)+1;
908 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
916 /****************************************************************************
917 Update a form struct.
918 ****************************************************************************/
920 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
924 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
926 DEBUG(106, ("[%s]\n", form_name
));
927 for (n
=0; n
<count
; n
++) {
928 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
929 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
933 if (n
==count
) return;
935 (*list
)[n
].flag
=form
->flags
;
936 (*list
)[n
].width
=form
->size_x
;
937 (*list
)[n
].length
=form
->size_y
;
938 (*list
)[n
].left
=form
->left
;
939 (*list
)[n
].top
=form
->top
;
940 (*list
)[n
].right
=form
->right
;
941 (*list
)[n
].bottom
=form
->bottom
;
944 /****************************************************************************
945 Get the nt drivers list.
946 Traverse the database and look-up the matching names.
947 ****************************************************************************/
948 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
951 const char *short_archi
;
954 TDB_DATA kbuf
, newkey
;
956 short_archi
= get_short_archi(architecture
);
957 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
959 for (kbuf
= tdb_firstkey(tdb_drivers
);
961 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
963 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
966 if((fl
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
967 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
972 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
979 /****************************************************************************
980 function to do the mapping between the long architecture name and
982 ****************************************************************************/
983 const char *get_short_archi(const char *long_archi
)
987 DEBUG(107,("Getting architecture dependant directory\n"));
990 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
991 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
993 if (archi_table
[i
].long_archi
==NULL
) {
994 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
998 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1001 DEBUGADD(108,("index: [%d]\n", i
));
1002 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
1003 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
1005 return archi_table
[i
].short_archi
;
1008 /****************************************************************************
1009 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1010 There are two case to be covered here: PE (Portable Executable) and NE (New
1011 Executable) files. Both files support the same INFO structure, but PE files
1012 store the signature in unicode, and NE files store it as !unicode.
1013 returns -1 on error, 1 on version info found, and 0 on no version info found.
1014 ****************************************************************************/
1016 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1022 if ((buf
=SMB_MALLOC(PE_HEADER_SIZE
)) == NULL
) {
1023 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1024 fname
, PE_HEADER_SIZE
));
1028 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1029 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1030 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1031 fname
, (unsigned long)byte_count
));
1032 goto no_version_info
;
1035 /* Is this really a DOS header? */
1036 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1037 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1038 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1039 goto no_version_info
;
1042 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1043 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1044 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1046 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1047 goto no_version_info
;
1050 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
1051 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1052 fname
, (unsigned long)byte_count
));
1053 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1054 goto no_version_info
;
1057 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1058 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1059 unsigned int num_sections
;
1060 unsigned int section_table_bytes
;
1062 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
1063 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1064 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
1065 /* At this point, we assume the file is in error. It still could be somthing
1066 * else besides a PE file, but it unlikely at this point.
1071 /* get the section table */
1072 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1073 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1074 if (section_table_bytes
== 0)
1078 if ((buf
=SMB_MALLOC(section_table_bytes
)) == NULL
) {
1079 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1080 fname
, section_table_bytes
));
1084 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1085 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1086 fname
, (unsigned long)byte_count
));
1090 /* Iterate the section table looking for the resource section ".rsrc" */
1091 for (i
= 0; i
< num_sections
; i
++) {
1092 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1094 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1095 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1096 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1098 if (section_bytes
== 0)
1102 if ((buf
=SMB_MALLOC(section_bytes
)) == NULL
) {
1103 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1104 fname
, section_bytes
));
1108 /* Seek to the start of the .rsrc section info */
1109 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1110 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1115 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1116 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1117 fname
, (unsigned long)byte_count
));
1121 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1124 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1125 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1126 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1127 /* Align to next long address */
1128 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1130 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1131 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1132 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1134 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1135 fname
, *major
, *minor
,
1136 (*major
>>16)&0xffff, *major
&0xffff,
1137 (*minor
>>16)&0xffff, *minor
&0xffff));
1146 /* Version info not found, fall back to origin date/time */
1147 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1151 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1152 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1153 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1154 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1155 /* At this point, we assume the file is in error. It still could be somthing
1156 * else besides a NE file, but it unlikely at this point. */
1160 /* Allocate a bit more space to speed up things */
1162 if ((buf
=SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1163 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1164 fname
, PE_HEADER_SIZE
));
1168 /* This is a HACK! I got tired of trying to sort through the messy
1169 * 'NE' file format. If anyone wants to clean this up please have at
1170 * it, but this works. 'NE' files will eventually fade away. JRR */
1171 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1172 /* Cover case that should not occur in a well formed 'NE' .dll file */
1173 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1175 for(i
=0; i
<byte_count
; i
++) {
1176 /* Fast skip past data that can't possibly match */
1177 if (buf
[i
] != 'V') continue;
1179 /* Potential match data crosses buf boundry, move it to beginning
1180 * of buf, and fill the buf with as much as it will hold. */
1181 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1184 memcpy(buf
, &buf
[i
], byte_count
-i
);
1185 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1186 (byte_count
-i
))) < 0) {
1188 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1193 byte_count
= bc
+ (byte_count
- i
);
1194 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1199 /* Check that the full signature string and the magic number that
1200 * follows exist (not a perfect solution, but the chances that this
1201 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1202 * twice, as it is simpler to read the code. */
1203 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1204 /* Compute skip alignment to next long address */
1205 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
1206 sizeof(VS_SIGNATURE
)) & 3;
1207 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1209 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1210 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1211 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1212 fname
, *major
, *minor
,
1213 (*major
>>16)&0xffff, *major
&0xffff,
1214 (*minor
>>16)&0xffff, *minor
&0xffff));
1221 /* Version info not found, fall back to origin date/time */
1222 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1227 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1228 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1229 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1240 /****************************************************************************
1241 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1242 share one or more files. During the MS installation process files are checked
1243 to insure that only a newer version of a shared file is installed over an
1244 older version. There are several possibilities for this comparison. If there
1245 is no previous version, the new one is newer (obviously). If either file is
1246 missing the version info structure, compare the creation date (on Unix use
1247 the modification date). Otherwise chose the numerically larger version number.
1248 ****************************************************************************/
1250 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1252 BOOL use_version
= True
;
1257 time_t new_create_time
;
1261 time_t old_create_time
;
1263 files_struct
*fsp
= NULL
;
1265 SMB_STRUCT_STAT stat_buf
;
1268 SET_STAT_INVALID(st
);
1269 SET_STAT_INVALID(stat_buf
);
1270 new_create_time
= (time_t)0;
1271 old_create_time
= (time_t)0;
1273 /* Get file version info (if available) for previous file (if it exists) */
1274 pstrcpy(filepath
, old_file
);
1276 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1278 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1280 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1283 FILE_ATTRIBUTE_NORMAL
,
1288 /* Old file not found, so by definition new file is in fact newer */
1289 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1294 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1300 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1302 use_version
= False
;
1303 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1304 old_create_time
= st
.st_mtime
;
1305 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1308 close_file(fsp
, True
);
1310 /* Get file version info (if available) for new file */
1311 pstrcpy(filepath
, new_file
);
1312 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1314 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1316 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1319 FILE_ATTRIBUTE_NORMAL
,
1324 /* New file not found, this shouldn't occur if the caller did its job */
1325 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1330 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1336 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1338 use_version
= False
;
1339 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1340 new_create_time
= st
.st_mtime
;
1341 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1344 close_file(fsp
, True
);
1346 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1347 /* Compare versions and choose the larger version number */
1348 if (new_major
> old_major
||
1349 (new_major
== old_major
&& new_minor
> old_minor
)) {
1351 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1355 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1360 /* Compare modification time/dates and choose the newest time/date */
1361 if (new_create_time
> old_create_time
) {
1362 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1366 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1373 close_file(fsp
, True
);
1377 /****************************************************************************
1378 Determine the correct cVersion associated with an architecture and driver
1379 ****************************************************************************/
1380 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1381 struct current_user
*user
, WERROR
*perr
)
1388 files_struct
*fsp
= NULL
;
1391 connection_struct
*conn
;
1393 SET_STAT_INVALID(st
);
1395 *perr
= WERR_INVALID_PARAM
;
1397 /* If architecture is Windows 95/98/ME, the version is always 0. */
1398 if (strcmp(architecture
, "WIN40") == 0) {
1399 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1405 * Connect to the print$ share under the same account as the user connected
1406 * to the rpc pipe. Note we must still be root to do this.
1409 /* Null password is ok - we are already an authenticated user... */
1410 null_pw
= data_blob(NULL
, 0);
1411 fstrcpy(res_type
, "A:");
1413 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1417 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1418 *perr
= ntstatus_to_werror(nt_status
);
1422 /* We are temporarily becoming the connection user. */
1423 if (!become_user(conn
, user
->vuid
)) {
1424 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1425 *perr
= WERR_ACCESS_DENIED
;
1429 /* Open the driver file (Portable Executable format) and determine the
1430 * deriver the cversion. */
1431 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1433 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1435 if ( !vfs_file_exist( conn
, driverpath
, &st
) ) {
1436 *perr
= WERR_BADFILE
;
1440 fsp
= open_file_ntcreate(conn
, driverpath
, &st
,
1442 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1445 FILE_ATTRIBUTE_NORMAL
,
1450 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1451 driverpath
, errno
));
1452 *perr
= WERR_ACCESS_DENIED
;
1457 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1458 if (ret
== -1) goto error_exit
;
1461 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1466 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1467 * for more details. Version in this case is not just the version of the
1468 * file, but the version in the sense of kernal mode (2) vs. user mode
1469 * (3) drivers. Other bits of the version fields are the version info.
1472 cversion
= major
& 0x0000ffff;
1474 case 2: /* WinNT drivers */
1475 case 3: /* Win2K drivers */
1479 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1480 driverpath
, cversion
));
1484 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1485 driverpath
, major
, minor
));
1488 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1489 driverpath
, cversion
));
1491 close_file(fsp
, True
);
1492 close_cnum(conn
, user
->vuid
);
1501 close_file(fsp
, True
);
1503 close_cnum(conn
, user
->vuid
);
1508 /****************************************************************************
1509 ****************************************************************************/
1510 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1511 struct current_user
*user
)
1513 const char *architecture
;
1519 /* clean up the driver name.
1520 * we can get .\driver.dll
1521 * or worse c:\windows\system\driver.dll !
1523 /* using an intermediate string to not have overlaping memcpy()'s */
1524 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1525 fstrcpy(new_name
, p
+1);
1526 fstrcpy(driver
->driverpath
, new_name
);
1529 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1530 fstrcpy(new_name
, p
+1);
1531 fstrcpy(driver
->datafile
, new_name
);
1534 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1535 fstrcpy(new_name
, p
+1);
1536 fstrcpy(driver
->configfile
, new_name
);
1539 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1540 fstrcpy(new_name
, p
+1);
1541 fstrcpy(driver
->helpfile
, new_name
);
1544 if (driver
->dependentfiles
) {
1545 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1546 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1547 fstrcpy(new_name
, p
+1);
1548 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1553 architecture
= get_short_archi(driver
->environment
);
1555 /* jfm:7/16/2000 the client always sends the cversion=0.
1556 * The server should check which version the driver is by reading
1557 * the PE header of driver->driverpath.
1559 * For Windows 95/98 the version is 0 (so the value sent is correct)
1560 * For Windows NT (the architecture doesn't matter)
1561 * NT 3.1: cversion=0
1562 * NT 3.5/3.51: cversion=1
1566 if ((driver
->cversion
= get_correct_cversion( architecture
, driver
->driverpath
, user
, &err
)) == -1)
1572 /****************************************************************************
1573 ****************************************************************************/
1574 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1576 const char *architecture
;
1582 /* clean up the driver name.
1583 * we can get .\driver.dll
1584 * or worse c:\windows\system\driver.dll !
1586 /* using an intermediate string to not have overlaping memcpy()'s */
1587 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1588 fstrcpy(new_name
, p
+1);
1589 fstrcpy(driver
->driverpath
, new_name
);
1592 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1593 fstrcpy(new_name
, p
+1);
1594 fstrcpy(driver
->datafile
, new_name
);
1597 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1598 fstrcpy(new_name
, p
+1);
1599 fstrcpy(driver
->configfile
, new_name
);
1602 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1603 fstrcpy(new_name
, p
+1);
1604 fstrcpy(driver
->helpfile
, new_name
);
1607 if (driver
->dependentfiles
) {
1608 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1609 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1610 fstrcpy(new_name
, p
+1);
1611 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1616 architecture
= get_short_archi(driver
->environment
);
1618 /* jfm:7/16/2000 the client always sends the cversion=0.
1619 * The server should check which version the driver is by reading
1620 * the PE header of driver->driverpath.
1622 * For Windows 95/98 the version is 0 (so the value sent is correct)
1623 * For Windows NT (the architecture doesn't matter)
1624 * NT 3.1: cversion=0
1625 * NT 3.5/3.51: cversion=1
1630 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1636 /****************************************************************************
1637 ****************************************************************************/
1638 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1639 uint32 level
, struct current_user
*user
)
1644 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1645 driver
=driver_abstract
.info_3
;
1646 return clean_up_driver_struct_level_3(driver
, user
);
1650 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1651 driver
=driver_abstract
.info_6
;
1652 return clean_up_driver_struct_level_6(driver
, user
);
1655 return WERR_INVALID_PARAM
;
1659 /****************************************************************************
1660 This function sucks and should be replaced. JRA.
1661 ****************************************************************************/
1663 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1665 dst
->cversion
= src
->version
;
1667 fstrcpy( dst
->name
, src
->name
);
1668 fstrcpy( dst
->environment
, src
->environment
);
1669 fstrcpy( dst
->driverpath
, src
->driverpath
);
1670 fstrcpy( dst
->datafile
, src
->datafile
);
1671 fstrcpy( dst
->configfile
, src
->configfile
);
1672 fstrcpy( dst
->helpfile
, src
->helpfile
);
1673 fstrcpy( dst
->monitorname
, src
->monitorname
);
1674 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1675 dst
->dependentfiles
= src
->dependentfiles
;
1678 #if 0 /* Debugging function */
1680 static char* ffmt(unsigned char *c
){
1682 static char ffmt_str
[17];
1684 for (i
=0; i
<16; i
++) {
1685 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1696 /****************************************************************************
1697 ****************************************************************************/
1698 WERROR
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1699 struct current_user
*user
, WERROR
*perr
)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1702 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1703 const char *architecture
;
1708 connection_struct
*conn
;
1719 memset(inbuf
, '\0', sizeof(inbuf
));
1720 memset(outbuf
, '\0', sizeof(outbuf
));
1724 driver
=driver_abstract
.info_3
;
1725 else if (level
==6) {
1726 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1727 driver
= &converted_driver
;
1729 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1730 return WERR_UNKNOWN_LEVEL
;
1733 architecture
= get_short_archi(driver
->environment
);
1736 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1737 * Note we must be root to do this.
1740 null_pw
= data_blob(NULL
, 0);
1741 fstrcpy(res_type
, "A:");
1743 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1747 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1748 *perr
= ntstatus_to_werror(nt_status
);
1749 return WERR_NO_SUCH_SHARE
;
1753 * Save who we are - we are temporarily becoming the connection user.
1756 if (!become_user(conn
, conn
->vuid
)) {
1757 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1758 return WERR_ACCESS_DENIED
;
1762 * make the directories version and version\driver_name
1763 * under the architecture directory.
1765 DEBUG(5,("Creating first directory\n"));
1766 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1767 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1768 mkdir_internal(conn
, new_dir
, bad_path
);
1770 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1771 * listed for this driver which has already been moved, skip it (note:
1772 * drivers may list the same file name several times. Then check if the
1773 * file already exists in archi\cversion\, if so, check that the version
1774 * info (or time stamps if version info is unavailable) is newer (or the
1775 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1776 * Otherwise, delete the file.
1778 * If a file is not moved to archi\cversion\ because of an error, all the
1779 * rest of the 'unmoved' driver files are removed from archi\. If one or
1780 * more of the driver's files was already moved to archi\cversion\, it
1781 * potentially leaves the driver in a partially updated state. Version
1782 * trauma will most likely occur if an client attempts to use any printer
1783 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1784 * done is appropriate... later JRR
1787 DEBUG(5,("Moving files now !\n"));
1789 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1790 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1791 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1792 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1793 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1794 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1795 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1796 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1797 new_name
, old_name
));
1798 *perr
= WERR_ACCESS_DENIED
;
1804 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1805 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1806 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1807 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1808 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1809 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1810 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1811 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1812 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1813 new_name
, old_name
));
1814 *perr
= WERR_ACCESS_DENIED
;
1821 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1822 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1823 !strequal(driver
->configfile
, driver
->datafile
)) {
1824 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1825 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1826 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1827 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1828 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1829 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1830 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1831 new_name
, old_name
));
1832 *perr
= WERR_ACCESS_DENIED
;
1839 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1840 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1841 !strequal(driver
->helpfile
, driver
->datafile
) &&
1842 !strequal(driver
->helpfile
, driver
->configfile
)) {
1843 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1844 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1845 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1846 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1847 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1848 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1849 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1850 new_name
, old_name
));
1851 *perr
= WERR_ACCESS_DENIED
;
1858 if (driver
->dependentfiles
) {
1859 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1860 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1861 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1862 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1863 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1865 for (j
=0; j
< i
; j
++) {
1866 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1871 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1872 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1873 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1874 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1875 if ( !copy_file(new_name
, old_name
, conn
,
1876 OPENX_FILE_EXISTS_TRUNCATE
|
1877 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1878 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1879 new_name
, old_name
));
1880 *perr
= WERR_ACCESS_DENIED
;
1889 close_cnum(conn
, user
->vuid
);
1892 return ver
!= -1 ? WERR_OK
: WERR_UNKNOWN_PRINTER_DRIVER
;
1895 /****************************************************************************
1896 ****************************************************************************/
1897 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1900 const char *architecture
;
1906 TDB_DATA kbuf
, dbuf
;
1908 architecture
= get_short_archi(driver
->environment
);
1910 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1911 * \\server is added in the rpc server layer.
1912 * It does make sense to NOT store the server's name in the printer TDB.
1915 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1917 /* .inf files do not always list a file for each of the four standard files.
1918 * Don't prepend a path to a null filename, or client claims:
1919 * "The server on which the printer resides does not have a suitable
1920 * <printer driver name> printer driver installed. Click OK if you
1921 * wish to install the driver on your local machine."
1923 if (strlen(driver
->driverpath
)) {
1924 fstrcpy(temp_name
, driver
->driverpath
);
1925 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1928 if (strlen(driver
->datafile
)) {
1929 fstrcpy(temp_name
, driver
->datafile
);
1930 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1933 if (strlen(driver
->configfile
)) {
1934 fstrcpy(temp_name
, driver
->configfile
);
1935 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1938 if (strlen(driver
->helpfile
)) {
1939 fstrcpy(temp_name
, driver
->helpfile
);
1940 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1943 if (driver
->dependentfiles
) {
1944 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1945 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1946 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1950 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1952 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1959 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1962 driver
->environment
,
1967 driver
->monitorname
,
1968 driver
->defaultdatatype
);
1970 if (driver
->dependentfiles
) {
1971 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1972 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1973 driver
->dependentfiles
[i
]);
1977 if (len
!= buflen
) {
1980 tb
= (char *)SMB_REALLOC(buf
, len
);
1982 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1993 kbuf
.dsize
= strlen(key
)+1;
1997 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
2001 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
2007 /****************************************************************************
2008 ****************************************************************************/
2009 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
2011 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
2014 info3
.cversion
= driver
->version
;
2015 fstrcpy(info3
.name
,driver
->name
);
2016 fstrcpy(info3
.environment
,driver
->environment
);
2017 fstrcpy(info3
.driverpath
,driver
->driverpath
);
2018 fstrcpy(info3
.datafile
,driver
->datafile
);
2019 fstrcpy(info3
.configfile
,driver
->configfile
);
2020 fstrcpy(info3
.helpfile
,driver
->helpfile
);
2021 fstrcpy(info3
.monitorname
,driver
->monitorname
);
2022 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
2023 info3
.dependentfiles
= driver
->dependentfiles
;
2025 return add_a_printer_driver_3(&info3
);
2029 /****************************************************************************
2030 ****************************************************************************/
2031 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
2033 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
2037 fstrcpy(info
.name
, driver
);
2038 fstrcpy(info
.defaultdatatype
, "RAW");
2040 fstrcpy(info
.driverpath
, "");
2041 fstrcpy(info
.datafile
, "");
2042 fstrcpy(info
.configfile
, "");
2043 fstrcpy(info
.helpfile
, "");
2045 if ((info
.dependentfiles
= SMB_MALLOC_ARRAY(fstring
, 2)) == NULL
)
2048 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
2049 fstrcpy(info
.dependentfiles
[0], "");
2051 *info_ptr
= memdup(&info
, sizeof(info
));
2056 /****************************************************************************
2057 ****************************************************************************/
2058 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
2060 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
2061 TDB_DATA kbuf
, dbuf
;
2062 const char *architecture
;
2067 ZERO_STRUCT(driver
);
2069 architecture
= get_short_archi(arch
);
2071 if ( !architecture
)
2072 return WERR_UNKNOWN_PRINTER_DRIVER
;
2074 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2076 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2079 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2081 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
2084 kbuf
.dsize
= strlen(key
)+1;
2086 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
2088 return WERR_UNKNOWN_PRINTER_DRIVER
;
2090 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2099 driver
.defaultdatatype
);
2102 while (len
< dbuf
.dsize
) {
2105 tddfs
= SMB_REALLOC_ARRAY(driver
.dependentfiles
, fstring
, i
+2);
2107 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2111 driver
.dependentfiles
= tddfs
;
2113 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2114 &driver
.dependentfiles
[i
]);
2118 if ( driver
.dependentfiles
)
2119 fstrcpy( driver
.dependentfiles
[i
], "" );
2121 SAFE_FREE(dbuf
.dptr
);
2123 if (len
!= dbuf
.dsize
) {
2124 SAFE_FREE(driver
.dependentfiles
);
2126 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
2129 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
2134 /****************************************************************************
2135 Debugging function, dump at level 6 the struct in the logs.
2136 ****************************************************************************/
2138 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2141 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
2144 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
2150 if (driver
.info_3
== NULL
)
2153 info3
=driver
.info_3
;
2155 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
2156 DEBUGADD(20,("name:[%s]\n", info3
->name
));
2157 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
2158 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
2159 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
2160 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
2161 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
2162 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
2163 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
2165 for (i
=0; info3
->dependentfiles
&&
2166 *info3
->dependentfiles
[i
]; i
++) {
2167 DEBUGADD(20,("dependentfile:[%s]\n",
2168 info3
->dependentfiles
[i
]));
2175 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
2183 /****************************************************************************
2184 ****************************************************************************/
2185 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
2189 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2194 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2195 nt_devmode
->devicename
,
2196 nt_devmode
->formname
,
2198 nt_devmode
->specversion
,
2199 nt_devmode
->driverversion
,
2201 nt_devmode
->driverextra
,
2202 nt_devmode
->orientation
,
2203 nt_devmode
->papersize
,
2204 nt_devmode
->paperlength
,
2205 nt_devmode
->paperwidth
,
2208 nt_devmode
->defaultsource
,
2209 nt_devmode
->printquality
,
2212 nt_devmode
->yresolution
,
2213 nt_devmode
->ttoption
,
2214 nt_devmode
->collate
,
2215 nt_devmode
->logpixels
,
2218 nt_devmode
->bitsperpel
,
2219 nt_devmode
->pelswidth
,
2220 nt_devmode
->pelsheight
,
2221 nt_devmode
->displayflags
,
2222 nt_devmode
->displayfrequency
,
2223 nt_devmode
->icmmethod
,
2224 nt_devmode
->icmintent
,
2225 nt_devmode
->mediatype
,
2226 nt_devmode
->dithertype
,
2227 nt_devmode
->reserved1
,
2228 nt_devmode
->reserved2
,
2229 nt_devmode
->panningwidth
,
2230 nt_devmode
->panningheight
,
2231 nt_devmode
->nt_dev_private
);
2234 if (nt_devmode
->nt_dev_private
) {
2235 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2236 nt_devmode
->driverextra
,
2237 nt_devmode
->nt_dev_private
);
2240 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2245 /****************************************************************************
2246 Pack all values in all printer keys
2247 ***************************************************************************/
2249 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2253 REGISTRY_VALUE
*val
;
2254 REGVAL_CTR
*val_ctr
;
2261 /* loop over all keys */
2263 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2264 val_ctr
= &data
->keys
[i
].values
;
2265 num_values
= regval_ctr_numvals( val_ctr
);
2267 /* pack the keyname followed by a empty value */
2269 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2270 &data
->keys
[i
].name
,
2276 /* now loop over all values */
2278 for ( j
=0; j
<num_values
; j
++ ) {
2279 /* pathname should be stored as <key>\<value> */
2281 val
= regval_ctr_specific_value( val_ctr
, j
);
2282 pstrcpy( path
, data
->keys
[i
].name
);
2283 pstrcat( path
, "\\" );
2284 pstrcat( path
, regval_name(val
) );
2286 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2291 regval_data_p(val
) );
2298 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2304 /****************************************************************************
2305 Delete a printer - this just deletes the printer info file, any open
2306 handles are not affected.
2307 ****************************************************************************/
2309 uint32
del_a_printer(const char *sharename
)
2313 pstring printdb_path
;
2315 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2317 kbuf
.dsize
=strlen(key
)+1;
2318 tdb_delete(tdb_printers
, kbuf
);
2320 slprintf(key
, sizeof(key
)-1, "%s%s", SECDESC_PREFIX
, sharename
);
2322 kbuf
.dsize
=strlen(key
)+1;
2323 tdb_delete(tdb_printers
, kbuf
);
2325 close_all_print_db();
2327 if (geteuid() == 0) {
2328 pstrcpy(printdb_path
, lock_path("printing/"));
2329 pstrcat(printdb_path
, sharename
);
2330 pstrcat(printdb_path
, ".tdb");
2332 unlink(printdb_path
);
2338 /****************************************************************************
2339 ****************************************************************************/
2340 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2345 TDB_DATA kbuf
, dbuf
;
2348 * in addprinter: no servername and the printer is the name
2349 * in setprinter: servername is \\server
2350 * and printer is \\server\\printer
2352 * Samba manages only local printers.
2353 * we currently don't support things like i
2354 * path=\\other_server\printer
2356 * We only store the printername, not \\server\printername
2359 if ( info
->servername
[0] != '\0' ) {
2360 trim_string(info
->printername
, info
->servername
, NULL
);
2361 trim_char(info
->printername
, '\\', '\0');
2362 info
->servername
[0]='\0';
2366 * JFM: one day I'll forget.
2367 * below that's info->portname because that's the SAMBA sharename
2368 * and I made NT 'thinks' it's the portname
2369 * the info->sharename is the thing you can name when you add a printer
2370 * that's the short-name when you create shared printer for 95/98
2371 * So I've made a limitation in SAMBA: you can only have 1 printer model
2372 * behind a SAMBA share.
2380 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2383 info
->default_priority
,
2400 info
->printprocessor
,
2404 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2406 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
2408 if (buflen
!= len
) {
2411 tb
= (char *)SMB_REALLOC(buf
, len
);
2413 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2423 kbuf
= make_printer_tdbkey( info
->sharename
);
2428 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2431 if (!W_ERROR_IS_OK(ret
))
2432 DEBUG(8, ("error updating printer to tdb on disk\n"));
2436 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2437 info
->sharename
, info
->drivername
, info
->portname
, len
));
2443 /****************************************************************************
2444 Malloc and return an NT devicemode.
2445 ****************************************************************************/
2447 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2450 char adevice
[MAXDEVICENAME
];
2451 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2453 if (nt_devmode
== NULL
) {
2454 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2458 ZERO_STRUCTP(nt_devmode
);
2460 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2461 fstrcpy(nt_devmode
->devicename
, adevice
);
2463 fstrcpy(nt_devmode
->formname
, "Letter");
2465 nt_devmode
->specversion
= 0x0401;
2466 nt_devmode
->driverversion
= 0x0400;
2467 nt_devmode
->size
= 0x00DC;
2468 nt_devmode
->driverextra
= 0x0000;
2469 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2470 DEFAULTSOURCE
| COPIES
| SCALE
|
2471 PAPERSIZE
| ORIENTATION
;
2472 nt_devmode
->orientation
= 1;
2473 nt_devmode
->papersize
= PAPER_LETTER
;
2474 nt_devmode
->paperlength
= 0;
2475 nt_devmode
->paperwidth
= 0;
2476 nt_devmode
->scale
= 0x64;
2477 nt_devmode
->copies
= 1;
2478 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2479 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2480 nt_devmode
->color
= COLOR_MONOCHROME
;
2481 nt_devmode
->duplex
= DUP_SIMPLEX
;
2482 nt_devmode
->yresolution
= 0;
2483 nt_devmode
->ttoption
= TT_SUBDEV
;
2484 nt_devmode
->collate
= COLLATE_FALSE
;
2485 nt_devmode
->icmmethod
= 0;
2486 nt_devmode
->icmintent
= 0;
2487 nt_devmode
->mediatype
= 0;
2488 nt_devmode
->dithertype
= 0;
2490 /* non utilisés par un driver d'imprimante */
2491 nt_devmode
->logpixels
= 0;
2492 nt_devmode
->bitsperpel
= 0;
2493 nt_devmode
->pelswidth
= 0;
2494 nt_devmode
->pelsheight
= 0;
2495 nt_devmode
->displayflags
= 0;
2496 nt_devmode
->displayfrequency
= 0;
2497 nt_devmode
->reserved1
= 0;
2498 nt_devmode
->reserved2
= 0;
2499 nt_devmode
->panningwidth
= 0;
2500 nt_devmode
->panningheight
= 0;
2502 nt_devmode
->nt_dev_private
= NULL
;
2506 /****************************************************************************
2507 Deepcopy an NT devicemode.
2508 ****************************************************************************/
2510 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2512 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2514 if ( !nt_devicemode
)
2517 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2518 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2522 new_nt_devicemode
->nt_dev_private
= NULL
;
2523 if (nt_devicemode
->nt_dev_private
!= NULL
) {
2524 if ((new_nt_devicemode
->nt_dev_private
= memdup(nt_devicemode
->nt_dev_private
, nt_devicemode
->driverextra
)) == NULL
) {
2525 SAFE_FREE(new_nt_devicemode
);
2526 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2531 return new_nt_devicemode
;
2534 /****************************************************************************
2535 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2536 ****************************************************************************/
2538 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2540 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2542 if(nt_devmode
== NULL
)
2545 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2547 SAFE_FREE(nt_devmode
->nt_dev_private
);
2548 SAFE_FREE(*devmode_ptr
);
2551 /****************************************************************************
2552 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2553 ****************************************************************************/
2554 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2556 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2557 NT_PRINTER_DATA
*data
;
2563 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2565 free_nt_devicemode(&info
->devmode
);
2567 /* clean up all registry keys */
2570 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2571 SAFE_FREE( data
->keys
[i
].name
);
2572 regval_ctr_destroy( &data
->keys
[i
].values
);
2574 SAFE_FREE( data
->keys
);
2576 /* finally the top level structure */
2578 SAFE_FREE( *info_ptr
);
2582 /****************************************************************************
2583 ****************************************************************************/
2584 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2588 NT_DEVICEMODE devmode
;
2590 ZERO_STRUCT(devmode
);
2592 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2594 if (!*nt_devmode
) return len
;
2596 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2600 &devmode
.specversion
,
2601 &devmode
.driverversion
,
2603 &devmode
.driverextra
,
2604 &devmode
.orientation
,
2606 &devmode
.paperlength
,
2607 &devmode
.paperwidth
,
2610 &devmode
.defaultsource
,
2611 &devmode
.printquality
,
2614 &devmode
.yresolution
,
2620 &devmode
.bitsperpel
,
2622 &devmode
.pelsheight
,
2623 &devmode
.displayflags
,
2624 &devmode
.displayfrequency
,
2628 &devmode
.dithertype
,
2631 &devmode
.panningwidth
,
2632 &devmode
.panningheight
,
2633 &devmode
.nt_dev_private
);
2635 if (devmode
.nt_dev_private
) {
2636 /* the len in tdb_unpack is an int value and
2637 * devmode.driverextra is only a short
2639 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2640 devmode
.driverextra
=(uint16
)extra_len
;
2642 /* check to catch an invalid TDB entry so we don't segfault */
2643 if (devmode
.driverextra
== 0) {
2644 devmode
.nt_dev_private
= NULL
;
2648 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2650 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2651 if (devmode
.nt_dev_private
)
2652 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2657 /****************************************************************************
2658 Allocate and initialize a new slot.
2659 ***************************************************************************/
2661 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2666 if ( !data
|| !name
)
2669 /* allocate another slot in the NT_PRINTER_KEY array */
2671 if ( !(d
= SMB_REALLOC_ARRAY( data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2672 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2678 key_index
= data
->num_keys
;
2680 /* initialze new key */
2683 data
->keys
[key_index
].name
= SMB_STRDUP( name
);
2685 regval_ctr_init( &data
->keys
[key_index
].values
);
2687 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2692 /****************************************************************************
2693 search for a registry key name in the existing printer data
2694 ***************************************************************************/
2696 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2699 NT_PRINTER_KEY
*printer_key
;
2701 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2702 if ( strequal( data
->keys
[i
].name
, name
) ) {
2704 /* cleanup memory */
2706 printer_key
= &data
->keys
[i
];
2707 SAFE_FREE( printer_key
->name
);
2708 regval_ctr_destroy( &printer_key
->values
);
2710 /* if not the end of the array, move remaining elements down one slot */
2713 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2714 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2721 return data
->num_keys
;
2724 /****************************************************************************
2725 search for a registry key name in the existing printer data
2726 ***************************************************************************/
2728 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2733 if ( !data
|| !name
)
2736 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2738 /* loop over all existing keys */
2740 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2741 if ( strequal(data
->keys
[i
].name
, name
) ) {
2742 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2752 /****************************************************************************
2753 ***************************************************************************/
2755 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2759 int num_subkeys
= 0;
2761 fstring
*ptr
, *subkeys_ptr
= NULL
;
2770 /* special case of asking for the top level printer data registry key names */
2772 if ( strlen(key
) == 0 ) {
2773 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2775 /* found a match, so allocate space and copy the name */
2777 if ( !(ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2778 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2780 SAFE_FREE( subkeys
);
2785 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2792 /* asking for the subkeys of some key */
2793 /* subkey paths are stored in the key name using '\' as the delimiter */
2795 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2796 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2798 /* if we found the exact key, then break */
2799 key_len
= strlen( key
);
2800 if ( strlen(data
->keys
[i
].name
) == key_len
)
2803 /* get subkey path */
2805 p
= data
->keys
[i
].name
+ key_len
;
2808 fstrcpy( subkeyname
, p
);
2809 if ( (p
= strchr( subkeyname
, '\\' )) )
2812 /* don't add a key more than once */
2814 for ( j
=0; j
<num_subkeys
; j
++ ) {
2815 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2819 if ( j
!= num_subkeys
)
2822 /* found a match, so allocate space and copy the name */
2824 if ( !(ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2825 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2827 SAFE_FREE( subkeys
);
2832 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2838 /* return error if the key was not found */
2840 if ( i
== data
->num_keys
)
2844 /* tag off the end */
2847 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2849 *subkeys
= subkeys_ptr
;
2855 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2858 smb_ucs2_t conv_str
[1024];
2861 regval_ctr_delvalue(ctr
, val_name
);
2862 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2863 STR_TERMINATE
| STR_NOALIGN
);
2864 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2865 (char *) conv_str
, str_size
);
2868 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2871 regval_ctr_delvalue(ctr
, val_name
);
2872 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2873 (char *) &dword
, sizeof(dword
));
2876 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2879 uint8 bin_bool
= (b
? 1 : 0);
2880 regval_ctr_delvalue(ctr
, val_name
);
2881 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2882 (char *) &bin_bool
, sizeof(bin_bool
));
2885 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2886 const char *multi_sz
)
2888 smb_ucs2_t
*conv_strs
= NULL
;
2891 /* a multi-sz has to have a null string terminator, i.e., the last
2892 string must be followed by two nulls */
2893 str_size
= strlen(multi_sz
) + 2;
2894 conv_strs
= SMB_CALLOC_ARRAY(smb_ucs2_t
, str_size
);
2899 /* Change to byte units. */
2900 str_size
*= sizeof(smb_ucs2_t
);
2901 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2902 STR_TERMINATE
| STR_NOALIGN
);
2904 regval_ctr_delvalue(ctr
, val_name
);
2905 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2906 (char *) conv_strs
, str_size
);
2907 safe_free(conv_strs
);
2911 /****************************************************************************
2912 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2914 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2915 * @return BOOL indicating success or failure
2916 ***************************************************************************/
2918 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2920 REGVAL_CTR
*ctr
= NULL
;
2923 char *allocated_string
= NULL
;
2924 const char *ascii_str
;
2927 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2928 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2929 ctr
= &info2
->data
.keys
[i
].values
;
2931 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2932 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2934 /* we make the assumption that the netbios name is the same
2935 as the DNS name sinc ethe former will be what we used to
2938 if ( get_mydnsdomname( dnssuffix
) )
2939 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2941 fstrcpy( longname
, global_myname() );
2943 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2945 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2946 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2947 SAFE_FREE(allocated_string
);
2949 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2950 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2951 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2952 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2953 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2954 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2955 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2956 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2957 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2959 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2960 (info2
->attributes
&
2961 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2963 switch (info2
->attributes
& 0x3) {
2965 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2968 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2971 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2974 ascii_str
= "unknown";
2976 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2981 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2985 REGVAL_CTR
*ctr
=NULL
;
2987 /* find the DsSpooler key */
2988 if ((i
= lookup_printerkey(&info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2989 i
= add_new_printer_key(&info2
->data
, SPOOL_DSSPOOLER_KEY
);
2990 ctr
= &info2
->data
.keys
[i
].values
;
2992 regval_ctr_delvalue(ctr
, "objectGUID");
2993 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2994 (char *) &guid
, sizeof(struct uuid
));
2997 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2998 NT_PRINTER_INFO_LEVEL
*printer
)
3002 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
3003 char *srv_dn_utf8
, **srv_cn_utf8
;
3006 const char *attrs
[] = {"objectGUID", NULL
};
3008 WERROR win_rc
= WERR_OK
;
3010 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
3012 /* figure out where to publish */
3013 ads_find_machine_acct(ads
, &res
, global_myname());
3015 /* We use ldap_get_dn here as we need the answer
3016 * in utf8 to call ldap_explode_dn(). JRA. */
3018 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
3021 return WERR_SERVER_UNAVAILABLE
;
3023 ads_msgfree(ads
, res
);
3024 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3026 ldap_memfree(srv_dn_utf8
);
3028 return WERR_SERVER_UNAVAILABLE
;
3030 /* Now convert to CH_UNIX. */
3031 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
3032 ldap_memfree(srv_dn_utf8
);
3033 ldap_memfree(srv_cn_utf8
);
3035 return WERR_SERVER_UNAVAILABLE
;
3037 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
3038 ldap_memfree(srv_dn_utf8
);
3039 ldap_memfree(srv_cn_utf8
);
3042 return WERR_SERVER_UNAVAILABLE
;
3045 ldap_memfree(srv_dn_utf8
);
3046 ldap_memfree(srv_cn_utf8
);
3048 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
3049 printer
->info_2
->sharename
, srv_dn
);
3052 SAFE_FREE(srv_cn_0
);
3054 /* build the ads mods */
3055 ctx
= talloc_init("nt_printer_publish_ads");
3056 mods
= ads_init_mods(ctx
);
3058 get_local_printer_publishing_data(ctx
, &mods
,
3059 &printer
->info_2
->data
);
3060 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3061 printer
->info_2
->sharename
);
3064 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3065 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
)
3066 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3068 if (!ADS_ERR_OK(ads_rc
))
3069 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3071 talloc_destroy(ctx
);
3073 /* retreive the guid and store it locally */
3074 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3076 ads_pull_guid(ads
, res
, &guid
);
3077 ads_msgfree(ads
, res
);
3078 store_printer_guid(printer
->info_2
, guid
);
3079 win_rc
= mod_a_printer(printer
, 2);
3086 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3087 NT_PRINTER_INFO_LEVEL
*printer
)
3091 char *prt_dn
= NULL
;
3093 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3095 /* remove the printer from the directory */
3096 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3097 printer
->info_2
->sharename
, global_myname());
3099 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
3100 prt_dn
= ads_get_dn(ads
, res
);
3101 ads_rc
= ads_del_dn(ads
, prt_dn
);
3102 ads_memfree(ads
, prt_dn
);
3105 ads_msgfree(ads
, res
);
3109 /****************************************************************************
3110 * Publish a printer in the directory
3112 * @param snum describing printer service
3113 * @return WERROR indicating status of publishing
3114 ***************************************************************************/
3116 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3119 ADS_STRUCT
*ads
= NULL
;
3120 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3123 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3124 if (!W_ERROR_IS_OK(win_rc
))
3128 case SPOOL_DS_PUBLISH
:
3129 case SPOOL_DS_UPDATE
:
3130 /* set the DsSpooler info and attributes */
3131 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3132 win_rc
= WERR_NOMEM
;
3136 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3138 case SPOOL_DS_UNPUBLISH
:
3139 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3142 win_rc
= WERR_NOT_SUPPORTED
;
3146 win_rc
= mod_a_printer(printer
, 2);
3147 if (!W_ERROR_IS_OK(win_rc
)) {
3148 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3152 ads
= ads_init(NULL
, NULL
, NULL
);
3154 DEBUG(3, ("ads_init() failed\n"));
3155 win_rc
= WERR_SERVER_UNAVAILABLE
;
3158 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3159 SAFE_FREE(ads
->auth
.password
);
3160 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3163 /* ads_connect() will find the DC for us */
3164 ads_rc
= ads_connect(ads
);
3165 if (!ADS_ERR_OK(ads_rc
)) {
3166 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3167 win_rc
= WERR_ACCESS_DENIED
;
3172 case SPOOL_DS_PUBLISH
:
3173 case SPOOL_DS_UPDATE
:
3174 win_rc
= nt_printer_publish_ads(ads
, printer
);
3176 case SPOOL_DS_UNPUBLISH
:
3177 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3182 free_a_printer(&printer
, 2);
3187 WERROR
check_published_printers(void)
3190 ADS_STRUCT
*ads
= NULL
;
3192 int n_services
= lp_numservices();
3193 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3195 ads
= ads_init(NULL
, NULL
, NULL
);
3197 DEBUG(3, ("ads_init() failed\n"));
3198 return WERR_SERVER_UNAVAILABLE
;
3200 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3201 SAFE_FREE(ads
->auth
.password
);
3202 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3205 /* ads_connect() will find the DC for us */
3206 ads_rc
= ads_connect(ads
);
3207 if (!ADS_ERR_OK(ads_rc
)) {
3208 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3210 return WERR_ACCESS_DENIED
;
3213 for (snum
= 0; snum
< n_services
; snum
++) {
3214 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3217 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3218 lp_servicename(snum
))) &&
3219 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3220 nt_printer_publish_ads(ads
, printer
);
3222 free_a_printer(&printer
, 2);
3229 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3232 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3234 REGISTRY_VALUE
*guid_val
;
3238 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3240 if (!W_ERROR_IS_OK(win_rc
) ||
3241 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3242 ((i
= lookup_printerkey(&printer
->info_2
->data
,
3243 SPOOL_DSSPOOLER_KEY
)) < 0) ||
3244 !(ctr
= &printer
->info_2
->data
.keys
[i
].values
) ||
3245 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID"))) {
3246 free_a_printer(&printer
, 2);
3250 /* fetching printer guids really ought to be a separate function.. */
3251 if (guid
&& regval_size(guid_val
) == sizeof(struct uuid
))
3252 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
3254 free_a_printer(&printer
, 2);
3258 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3263 WERROR
check_published_printers(void)
3268 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3273 #endif /* HAVE_ADS */
3275 /****************************************************************************
3276 ***************************************************************************/
3278 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3280 NT_PRINTER_DATA
*data
;
3282 int removed_keys
= 0;
3286 empty_slot
= data
->num_keys
;
3289 return WERR_INVALID_PARAM
;
3291 /* remove all keys */
3293 if ( !strlen(key
) ) {
3294 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3295 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3296 data
->keys
[i
].name
));
3298 SAFE_FREE( data
->keys
[i
].name
);
3299 regval_ctr_destroy( &data
->keys
[i
].values
);
3302 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3305 SAFE_FREE( data
->keys
);
3306 ZERO_STRUCTP( data
);
3311 /* remove a specific key (and all subkeys) */
3313 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3314 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3315 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3316 data
->keys
[i
].name
));
3318 SAFE_FREE( data
->keys
[i
].name
);
3319 regval_ctr_destroy( &data
->keys
[i
].values
);
3321 /* mark the slot as empty */
3323 ZERO_STRUCTP( &data
->keys
[i
] );
3327 /* find the first empty slot */
3329 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3330 if ( !data
->keys
[i
].name
) {
3337 if ( i
== data
->num_keys
)
3338 /* nothing was removed */
3339 return WERR_INVALID_PARAM
;
3341 /* move everything down */
3343 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3344 if ( data
->keys
[i
].name
) {
3345 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3346 ZERO_STRUCTP( &data
->keys
[i
] );
3354 data
->num_keys
-= removed_keys
;
3356 /* sanity check to see if anything is left */
3358 if ( !data
->num_keys
) {
3359 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3361 SAFE_FREE( data
->keys
);
3362 ZERO_STRUCTP( data
);
3368 /****************************************************************************
3369 ***************************************************************************/
3371 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3373 WERROR result
= WERR_OK
;
3376 /* we must have names on non-zero length */
3378 if ( !key
|| !*key
|| !value
|| !*value
)
3379 return WERR_INVALID_NAME
;
3381 /* find the printer key first */
3383 key_index
= lookup_printerkey( &p2
->data
, key
);
3384 if ( key_index
== -1 )
3387 /* make sure the value exists so we can return the correct error code */
3389 if ( !regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
) )
3390 return WERR_BADFILE
;
3392 regval_ctr_delvalue( &p2
->data
.keys
[key_index
].values
, value
);
3394 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3400 /****************************************************************************
3401 ***************************************************************************/
3403 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3404 uint32 type
, uint8
*data
, int real_len
)
3406 WERROR result
= WERR_OK
;
3409 /* we must have names on non-zero length */
3411 if ( !key
|| !*key
|| !value
|| !*value
)
3412 return WERR_INVALID_NAME
;
3414 /* find the printer key first */
3416 key_index
= lookup_printerkey( &p2
->data
, key
);
3417 if ( key_index
== -1 )
3418 key_index
= add_new_printer_key( &p2
->data
, key
);
3420 if ( key_index
== -1 )
3423 regval_ctr_addvalue( &p2
->data
.keys
[key_index
].values
, value
,
3424 type
, (const char *)data
, real_len
);
3426 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3427 key
, value
, type
, real_len
));
3432 /****************************************************************************
3433 ***************************************************************************/
3435 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3439 if ( (key_index
= lookup_printerkey( &p2
->data
, key
)) == -1 )
3442 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3445 return regval_ctr_getvalue( &p2
->data
.keys
[key_index
].values
, value
);
3448 /****************************************************************************
3449 Unpack a list of registry values frem the TDB
3450 ***************************************************************************/
3452 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3456 pstring string
, valuename
, keyname
;
3460 REGISTRY_VALUE
*regval_p
;
3463 /* add the "PrinterDriverData" key first for performance reasons */
3465 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3467 /* loop and unpack the rest of the registry values */
3471 /* check to see if there are any more registry values */
3474 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3478 /* unpack the next regval */
3480 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3486 /* lookup for subkey names which have a type of REG_NONE */
3487 /* there's no data with this entry */
3489 if ( type
== REG_NONE
) {
3490 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3491 add_new_printer_key( printer_data
, string
);
3496 * break of the keyname from the value name.
3497 * Valuenames can have embedded '\'s so be careful.
3498 * only support one level of keys. See the
3499 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3503 str
= strchr_m( string
, '\\');
3505 /* Put in "PrinterDriverData" is no key specified */
3508 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3509 pstrcpy( valuename
, string
);
3513 pstrcpy( keyname
, string
);
3514 pstrcpy( valuename
, str
+1 );
3517 /* see if we need a new key */
3519 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3520 key_index
= add_new_printer_key( printer_data
, keyname
);
3522 if ( key_index
== -1 ) {
3523 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3528 /* add the new value */
3530 regval_ctr_addvalue( &printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3532 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3534 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3540 /****************************************************************************
3541 ***************************************************************************/
3543 static void map_to_os2_driver(fstring drivername
)
3545 static BOOL initialised
=False
;
3546 static fstring last_from
,last_to
;
3547 char *mapfile
= lp_os2_driver_map();
3548 char **lines
= NULL
;
3552 if (!strlen(drivername
))
3559 *last_from
= *last_to
= 0;
3563 if (strequal(drivername
,last_from
)) {
3564 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3565 fstrcpy(drivername
,last_to
);
3569 lines
= file_lines_load(mapfile
, &numlines
);
3570 if (numlines
== 0) {
3571 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3575 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3577 for( i
= 0; i
< numlines
; i
++) {
3578 char *nt_name
= lines
[i
];
3579 char *os2_name
= strchr(nt_name
,'=');
3586 while (isspace(*nt_name
))
3589 if (!*nt_name
|| strchr("#;",*nt_name
))
3593 int l
= strlen(nt_name
);
3594 while (l
&& isspace(nt_name
[l
-1])) {
3600 while (isspace(*os2_name
))
3604 int l
= strlen(os2_name
);
3605 while (l
&& isspace(os2_name
[l
-1])) {
3611 if (strequal(nt_name
,drivername
)) {
3612 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3613 fstrcpy(last_from
,drivername
);
3614 fstrcpy(last_to
,os2_name
);
3615 fstrcpy(drivername
,os2_name
);
3616 file_lines_free(lines
);
3621 file_lines_free(lines
);
3624 /****************************************************************************
3625 Get a default printer info 2 struct.
3626 ****************************************************************************/
3627 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char* sharename
)
3630 NT_PRINTER_INFO_LEVEL_2 info
;
3634 snum
= lp_servicenumber(sharename
);
3636 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3637 slprintf(info
.printername
, sizeof(info
.printername
)-1, "\\\\%s\\%s",
3638 servername
, sharename
);
3639 fstrcpy(info
.sharename
, sharename
);
3640 fstrcpy(info
.portname
, SAMBA_PRINTER_PORT_NAME
);
3642 /* by setting the driver name to an empty string, a local NT admin
3643 can now run the **local** APW to install a local printer driver
3644 for a Samba shared printer in 2.2. Without this, drivers **must** be
3645 installed on the Samba server for NT clients --jerry */
3646 #if 0 /* JERRY --do not uncomment-- */
3647 if (!*info
.drivername
)
3648 fstrcpy(info
.drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3652 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
.drivername
));
3654 pstrcpy(info
.comment
, "");
3655 fstrcpy(info
.printprocessor
, "winprint");
3656 fstrcpy(info
.datatype
, "RAW");
3658 info
.attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3660 info
.starttime
= 0; /* Minutes since 12:00am GMT */
3661 info
.untiltime
= 0; /* Minutes since 12:00am GMT */
3663 info
.default_priority
= 1;
3664 info
.setuptime
= (uint32
)time(NULL
);
3667 * I changed this as I think it is better to have a generic
3668 * DEVMODE than to crash Win2k explorer.exe --jerry
3669 * See the HP Deskjet 990c Win2k drivers for an example.
3671 * However the default devmode appears to cause problems
3672 * with the HP CLJ 8500 PCL driver. Hence the addition of
3673 * the "default devmode" parameter --jerry 22/01/2002
3676 if (lp_default_devmode(snum
)) {
3677 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
3681 info
.devmode
= NULL
;
3684 /* This will get the current RPC talloc context, but we should be
3685 passing this as a parameter... fixme... JRA ! */
3687 if (!nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
))
3690 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
3692 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3700 free_nt_devicemode(&info
.devmode
);
3701 return WERR_ACCESS_DENIED
;
3704 /****************************************************************************
3705 ****************************************************************************/
3706 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, const char *servername
, const char *sharename
)
3708 NT_PRINTER_INFO_LEVEL_2 info
;
3710 int snum
= lp_servicenumber(sharename
);
3711 TDB_DATA kbuf
, dbuf
;
3712 fstring printername
;
3713 char adevice
[MAXDEVICENAME
];
3717 kbuf
= make_printer_tdbkey( sharename
);
3719 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3721 return get_a_printer_2_default(info_ptr
, servername
, sharename
);
3723 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3726 &info
.default_priority
,
3743 info
.printprocessor
,
3747 /* Samba has to have shared raw drivers. */
3748 info
.attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3749 info
.attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3751 /* Restore the stripped strings. */
3752 slprintf(info
.servername
, sizeof(info
.servername
)-1, "\\\\%s", servername
);
3754 if ( lp_force_printername(snum
) )
3755 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3757 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
.printername
);
3759 fstrcpy(info
.printername
, printername
);
3761 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3764 * Some client drivers freak out if there is a NULL devmode
3765 * (probably the driver is not checking before accessing
3766 * the devmode pointer) --jerry
3768 * See comments in get_a_printer_2_default()
3771 if (lp_default_devmode(snum
) && !info
.devmode
) {
3772 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3774 info
.devmode
= construct_nt_devicemode(printername
);
3777 slprintf( adevice
, sizeof(adevice
), "%s", info
.printername
);
3779 fstrcpy(info
.devmode
->devicename
, adevice
);
3782 len
+= unpack_values( &info
.data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3784 /* This will get the current RPC talloc context, but we should be
3785 passing this as a parameter... fixme... JRA ! */
3787 nt_printing_getsec(get_talloc_ctx(), sharename
, &info
.secdesc_buf
);
3789 /* Fix for OS/2 drivers. */
3791 if (get_remote_arch() == RA_OS2
)
3792 map_to_os2_driver(info
.drivername
);
3794 SAFE_FREE(dbuf
.dptr
);
3795 *info_ptr
=memdup(&info
, sizeof(info
));
3797 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3798 sharename
, info
.printername
, info
.drivername
));
3803 /****************************************************************************
3804 Debugging function, dump at level 6 the struct in the logs.
3805 ****************************************************************************/
3806 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3809 NT_PRINTER_INFO_LEVEL_2
*info2
;
3811 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3816 if (printer
->info_2
== NULL
)
3820 info2
=printer
->info_2
;
3822 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3823 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3824 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3825 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3826 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3827 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3828 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3829 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3830 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3831 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3832 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3834 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3835 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3836 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3837 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3838 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3839 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3840 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3841 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3842 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3843 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3844 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3850 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3858 /****************************************************************************
3859 Update the changeid time.
3860 This is SO NASTY as some drivers need this to change, others need it
3861 static. This value will change every second, and I must hope that this
3862 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3864 ****************************************************************************/
3866 static uint32
rev_changeid(void)
3870 get_process_uptime(&tv
);
3873 /* Return changeid as msec since spooler restart */
3874 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3877 * This setting seems to work well but is too untested
3878 * to replace the above calculation. Left in for experiementation
3879 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3881 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3885 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
3886 /********************************************************************
3887 Send a message to all smbds about the printer that just changed
3888 ********************************************************************/
3890 static BOOL
send_printer_mod_msg( char* printername
)
3892 int len
= strlen(printername
);
3897 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3900 /* spam everyone that we just changed this printer */
3902 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD
, printername
, len
+1, False
, NULL
);
3910 * The function below are the high level ones.
3911 * only those ones must be called from the spoolss code.
3915 /****************************************************************************
3916 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3917 ****************************************************************************/
3919 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3923 dump_a_printer(printer
, level
);
3925 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
3927 * invalidate cache for all open handles to this printer.
3928 * cache for a given handle will be updated on the next
3932 invalidate_printer_hnd_cache( printer
->info_2
->sharename
);
3934 /* messages between smbds can only be sent as root */
3936 send_printer_mod_msg( printer
->info_2
->sharename
);
3944 * Update the changestamp. Emperical tests show that the
3945 * ChangeID is always updated,but c_setprinter is
3946 * global spooler variable (not per printer).
3949 /* ChangeID **must** be increasing over the lifetime
3950 of client's spoolss service in order for the
3951 client's cache to show updates */
3953 printer
->info_2
->changeid
= rev_changeid();
3956 * Because one day someone will ask:
3957 * NT->NT An admin connection to a remote
3958 * printer show changes imeediately in
3959 * the properities dialog
3961 * A non-admin connection will only show the
3962 * changes after viewing the properites page
3963 * 2 times. Seems to be related to a
3964 * race condition in the client between the spooler
3965 * updating the local cache and the Explorer.exe GUI
3966 * actually displaying the properties.
3968 * This is fixed in Win2k. admin/non-admin
3969 * connections both display changes immediately.
3974 result
=update_a_printer_2(printer
->info_2
);
3979 result
=WERR_UNKNOWN_LEVEL
;
3986 /****************************************************************************
3987 Initialize printer devmode & data with previously saved driver init values.
3988 ****************************************************************************/
3990 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3994 TDB_DATA kbuf
, dbuf
;
3995 NT_PRINTER_INFO_LEVEL_2 info
;
4001 * Delete any printer data 'values' already set. When called for driver
4002 * replace, there will generally be some, but during an add printer, there
4003 * should not be any (if there are delete them).
4006 delete_all_printer_data( info_ptr
, "" );
4008 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
4011 kbuf
.dsize
= strlen(key
)+1;
4013 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
4016 * When changing to a driver that has no init info in the tdb, remove
4017 * the previous drivers init info and leave the new on blank.
4019 free_nt_devicemode(&info_ptr
->devmode
);
4024 * Get the saved DEVMODE..
4027 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4030 * The saved DEVMODE contains the devicename from the printer used during
4031 * the initialization save. Change it to reflect the new printer.
4034 if ( info
.devmode
) {
4035 ZERO_STRUCT(info
.devmode
->devicename
);
4036 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
4040 * NT/2k does not change out the entire DeviceMode of a printer
4041 * when changing the driver. Only the driverextra, private, &
4042 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4044 * Later examination revealed that Windows NT/2k does reset the
4045 * the printer's device mode, bit **only** when you change a
4046 * property of the device mode such as the page orientation.
4051 /* Bind the saved DEVMODE to the new the printer */
4053 free_nt_devicemode(&info_ptr
->devmode
);
4054 info_ptr
->devmode
= info
.devmode
;
4056 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4057 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
4059 /* Add the printer data 'values' to the new printer */
4061 len
+= unpack_values( &info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4064 SAFE_FREE(dbuf
.dptr
);
4069 /****************************************************************************
4070 Initialize printer devmode & data with previously saved driver init values.
4071 When a printer is created using AddPrinter, the drivername bound to the
4072 printer is used to lookup previously saved driver initialization info, which
4073 is bound to the new printer.
4074 ****************************************************************************/
4076 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4078 BOOL result
= False
;
4082 result
= set_driver_init_2(printer
->info_2
);
4086 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4094 /****************************************************************************
4095 Delete driver init data stored for a specified driver
4096 ****************************************************************************/
4098 BOOL
del_driver_init(char *drivername
)
4103 if (!drivername
|| !*drivername
) {
4104 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4108 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
4111 kbuf
.dsize
= strlen(key
)+1;
4113 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
4115 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
4118 /****************************************************************************
4119 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4120 in the tdb. Note: this is different from the driver entry and the printer
4121 entry. There should be a single driver init entry for each driver regardless
4122 of whether it was installed from NT or 2K. Technically, they should be
4123 different, but they work out to the same struct.
4124 ****************************************************************************/
4126 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4130 int buflen
, len
, ret
;
4131 TDB_DATA kbuf
, dbuf
;
4138 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4140 len
+= pack_values( &info
->data
, buf
+len
, buflen
-len
);
4145 tb
= (char *)SMB_REALLOC(buf
, len
);
4147 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4157 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
4160 kbuf
.dsize
= strlen(key
)+1;
4164 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
4168 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4172 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4173 info
->sharename
, info
->drivername
));
4178 /****************************************************************************
4179 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4180 ****************************************************************************/
4182 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4186 dump_a_printer(printer
, level
);
4190 result
= update_driver_init_2(printer
->info_2
);
4200 /****************************************************************************
4201 Convert the printer data value, a REG_BINARY array, into an initialization
4202 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4203 got to keep the endians happy :).
4204 ****************************************************************************/
4206 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
4208 BOOL result
= False
;
4212 ZERO_STRUCT(devmode
);
4214 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
4215 ps
.data_p
= (char *)data
;
4216 ps
.buffer_size
= data_len
;
4218 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
4219 result
= convert_devicemode("", &devmode
, &nt_devmode
);
4221 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4226 /****************************************************************************
4227 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4229 1. Use the driver's config DLL to this UNC printername and:
4230 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4231 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4232 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4234 The last step triggers saving the "driver initialization" information for
4235 this printer into the tdb. Later, new printers that use this driver will
4236 have this initialization information bound to them. This simulates the
4237 driver initialization, as if it had run on the Samba server (as it would
4240 The Win32 client side code requirement sucks! But until we can run arbitrary
4241 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4243 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4244 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4245 about it and you will realize why. JRR 010720
4246 ****************************************************************************/
4248 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4250 WERROR status
= WERR_OK
;
4251 TALLOC_CTX
*ctx
= NULL
;
4252 NT_DEVICEMODE
*nt_devmode
= NULL
;
4253 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4256 * When the DEVMODE is already set on the printer, don't try to unpack it.
4258 DEBUG(8,("save_driver_init_2: Enter...\n"));
4260 if ( !printer
->info_2
->devmode
&& data_len
) {
4262 * Set devmode on printer info, so entire printer initialization can be
4266 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4269 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4270 status
= WERR_NOMEM
;
4274 ZERO_STRUCTP(nt_devmode
);
4277 * The DEVMODE is held in the 'data' component of the param in raw binary.
4278 * Convert it to to a devmode structure
4280 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4281 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4282 status
= WERR_INVALID_PARAM
;
4286 printer
->info_2
->devmode
= nt_devmode
;
4290 * Pack up and add (or update) the DEVMODE and any current printer data to
4291 * a 'driver init' element in the tdb
4295 if ( update_driver_init(printer
, 2) != 0 ) {
4296 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4297 status
= WERR_NOMEM
;
4302 * If driver initialization info was successfully saved, set the current
4303 * printer to match it. This allows initialization of the current printer
4304 * as well as the driver.
4306 status
= mod_a_printer(printer
, 2);
4307 if (!W_ERROR_IS_OK(status
)) {
4308 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4309 printer
->info_2
->printername
));
4313 talloc_destroy(ctx
);
4314 free_nt_devicemode( &nt_devmode
);
4316 printer
->info_2
->devmode
= tmp_devmode
;
4321 /****************************************************************************
4322 Update the driver init info (DEVMODE and specifics) for a printer
4323 ****************************************************************************/
4325 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4327 WERROR status
= WERR_OK
;
4331 status
= save_driver_init_2( printer
, data
, data_len
);
4334 status
= WERR_UNKNOWN_LEVEL
;
4341 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4342 /****************************************************************************
4343 Deep copy a NT_PRINTER_DATA
4344 ****************************************************************************/
4346 static NTSTATUS
copy_printer_data( NT_PRINTER_DATA
*dst
, NT_PRINTER_DATA
*src
)
4348 int i
, j
, num_vals
, new_key_index
;
4349 REGVAL_CTR
*src_key
, *dst_key
;
4352 return NT_STATUS_NO_MEMORY
;
4354 for ( i
=0; i
<src
->num_keys
; i
++ ) {
4356 /* create a new instance of the printerkey in the destination
4357 printer_data object */
4359 new_key_index
= add_new_printer_key( dst
, src
->keys
[i
].name
);
4360 dst_key
= &dst
->keys
[new_key_index
].values
;
4362 src_key
= &src
->keys
[i
].values
;
4363 num_vals
= regval_ctr_numvals( src_key
);
4365 /* dup the printer entire printer key */
4367 for ( j
=0; j
<num_vals
; j
++ ) {
4368 regval_ctr_copyvalue( dst_key
, regval_ctr_specific_value(src_key
, j
) );
4372 return NT_STATUS_OK
;
4375 /****************************************************************************
4376 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4378 ****************************************************************************/
4380 NT_PRINTER_INFO_LEVEL_2
* dup_printer_2( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
*printer
)
4382 NT_PRINTER_INFO_LEVEL_2
*copy
;
4387 if ( !(copy
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL_2
)) )
4390 memcpy( copy
, printer
, sizeof(NT_PRINTER_INFO_LEVEL_2
) );
4392 /* malloc()'d members copied here */
4394 copy
->devmode
= dup_nt_devicemode( printer
->devmode
);
4396 ZERO_STRUCT( copy
->data
);
4397 copy_printer_data( ©
->data
, &printer
->data
);
4399 /* this is talloc()'d; very ugly that we have a structure that
4400 is half malloc()'d and half talloc()'d but that is the way
4401 that the PRINTER_INFO stuff is written right now. --jerry */
4403 copy
->secdesc_buf
= dup_sec_desc_buf( ctx
, printer
->secdesc_buf
);
4409 /****************************************************************************
4410 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4412 Previously the code had a memory allocation problem because it always
4413 used the TALLOC_CTX from the Printer_entry*. This context lasts
4414 as a long as the original handle is open. So if the client made a lot
4415 of getprinter[data]() calls, the memory usage would climb. Now we use
4416 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4417 still use the Printer_entry->ctx for maintaining the cache copy though
4418 since that object must live as long as the handle by definition.
4421 ****************************************************************************/
4423 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4424 const char *sharename
)
4427 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4432 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4436 if ((printer
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL
)) == NULL
) {
4437 DEBUG(0,("get_a_printer: malloc fail.\n"));
4440 ZERO_STRUCTP(printer
);
4443 fstrcpy( servername
, print_hnd
->servername
);
4445 fstrcpy( servername
, "%L" );
4446 standard_sub_basic( "", servername
, sizeof(servername
)-1 );
4449 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4452 * check for cache first. A Printer handle cannot changed
4453 * to another printer object so we only check that the printer
4454 * is actually for a printer and that the printer_info pointer
4458 && (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
4459 && print_hnd
->printer_info
)
4461 /* get_talloc_ctx() works here because we need a short
4462 lived talloc context */
4464 if ( !(printer
->info_2
= dup_printer_2(get_talloc_ctx(), print_hnd
->printer_info
->info_2
)) )
4466 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4472 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4474 *pp_printer
= printer
;
4480 /* no cache for this handle; see if we can match one from another handle.
4481 Make sure to use a short lived talloc ctx */
4484 result
= find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer
->info_2
, servername
, sharename
);
4486 /* fail to disk if we don't have it with any open handle */
4488 if ( !print_hnd
|| !W_ERROR_IS_OK(result
) )
4489 result
= get_a_printer_2(&printer
->info_2
, servername
, sharename
);
4491 result
= get_a_printer_2(&printer
->info_2
, servername
, sharename
);
4495 /* we have a new printer now. Save it with this handle */
4497 if ( W_ERROR_IS_OK(result
) ) {
4498 dump_a_printer(printer
, level
);
4500 #ifdef ENABLE_PRINT_HND_OBJECT_CACHE
4501 /* save a copy in cache */
4502 if ( print_hnd
&& (print_hnd
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)) {
4503 if ( !print_hnd
->printer_info
)
4504 print_hnd
->printer_info
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL
);
4506 if ( print_hnd
->printer_info
) {
4507 /* make sure to use the handle's talloc ctx here since
4508 the printer_2 object must last until the handle is closed */
4510 print_hnd
->printer_info
->info_2
= dup_printer_2(print_hnd
->ctx
, printer
->info_2
);
4512 /* don't fail the lookup just because the cache update failed */
4513 if ( !print_hnd
->printer_info
->info_2
)
4514 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4518 *pp_printer
= printer
;
4526 result
=WERR_UNKNOWN_LEVEL
;
4530 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename
, (unsigned int)level
, dos_errstr(result
)));
4535 /****************************************************************************
4536 Deletes a NT_PRINTER_INFO_LEVEL struct.
4537 ****************************************************************************/
4539 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4542 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4544 DEBUG(104,("freeing a printer at level [%d]\n", level
));
4546 if (printer
== NULL
)
4551 if (printer
->info_2
!= NULL
) {
4552 free_nt_printer_info_level_2(&printer
->info_2
);
4563 SAFE_FREE(*pp_printer
);
4567 /****************************************************************************
4568 ****************************************************************************/
4569 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4572 DEBUG(104,("adding a printer at level [%d]\n", level
));
4573 dump_a_printer_driver(driver
, level
);
4577 result
=add_a_printer_driver_3(driver
.info_3
);
4581 result
=add_a_printer_driver_6(driver
.info_6
);
4591 /****************************************************************************
4592 ****************************************************************************/
4594 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4595 fstring drivername
, const char *architecture
, uint32 version
)
4601 /* Sometime we just want any version of the driver */
4603 if ( version
== DRIVER_ANY_VERSION
) {
4604 /* look for Win2k first and then for NT4 */
4605 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4608 if ( !W_ERROR_IS_OK(result
) ) {
4609 result
= get_a_printer_driver_3( &driver
->info_3
,
4610 drivername
, architecture
, 2 );
4613 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4614 architecture
, version
);
4623 if (W_ERROR_IS_OK(result
))
4624 dump_a_printer_driver(*driver
, level
);
4629 /****************************************************************************
4630 ****************************************************************************/
4631 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4638 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4639 if (driver
.info_3
!= NULL
)
4641 info3
=driver
.info_3
;
4642 SAFE_FREE(info3
->dependentfiles
);
4643 ZERO_STRUCTP(info3
);
4653 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4654 if (driver
.info_6
!= NULL
) {
4655 info6
=driver
.info_6
;
4656 SAFE_FREE(info6
->dependentfiles
);
4657 SAFE_FREE(info6
->previousnames
);
4658 ZERO_STRUCTP(info6
);
4674 /****************************************************************************
4675 Determine whether or not a particular driver is currently assigned
4677 ****************************************************************************/
4679 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4682 int n_services
= lp_numservices();
4683 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4684 BOOL in_use
= False
;
4689 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4691 /* loop through the printers.tdb and check for the drivername */
4693 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4694 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4697 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4700 if ( strequal(info_3
->name
, printer
->info_2
->drivername
) )
4703 free_a_printer( &printer
, 2 );
4706 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4709 NT_PRINTER_DRIVER_INFO_LEVEL d
;
4712 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3
->name
));
4714 /* we can still remove the driver if there is one of
4715 "Windows NT x86" version 2 or 3 left */
4717 if ( !strequal( "Windows NT x86", info_3
->environment
) ) {
4718 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4721 switch ( info_3
->cversion
) {
4723 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 3 );
4726 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 2 );
4729 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4731 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4736 /* now check the error code */
4738 if ( W_ERROR_IS_OK(werr
) ) {
4739 /* it's ok to remove the driver, we have other architctures left */
4741 free_a_printer_driver( d
, 3 );
4745 /* report that the driver is not in use by default */
4751 /**********************************************************************
4752 Check to see if a ogiven file is in use by *info
4753 *********************************************************************/
4755 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4762 if ( strequal(file
, info
->driverpath
) )
4765 if ( strequal(file
, info
->datafile
) )
4768 if ( strequal(file
, info
->configfile
) )
4771 if ( strequal(file
, info
->helpfile
) )
4774 /* see of there are any dependent files to examine */
4776 if ( !info
->dependentfiles
)
4779 while ( *info
->dependentfiles
[i
] ) {
4780 if ( strequal(file
, info
->dependentfiles
[i
]) )
4789 /**********************************************************************
4790 Utility function to remove the dependent file pointed to by the
4791 input parameter from the list
4792 *********************************************************************/
4794 static void trim_dependent_file( fstring files
[], int idx
)
4797 /* bump everything down a slot */
4799 while( *files
[idx
+1] ) {
4800 fstrcpy( files
[idx
], files
[idx
+1] );
4809 /**********************************************************************
4810 Check if any of the files used by src are also used by drv
4811 *********************************************************************/
4813 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4814 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4816 BOOL in_use
= False
;
4822 /* check each file. Remove it from the src structure if it overlaps */
4824 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4826 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4827 fstrcpy( src
->driverpath
, "" );
4830 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4832 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4833 fstrcpy( src
->datafile
, "" );
4836 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4838 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4839 fstrcpy( src
->configfile
, "" );
4842 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4844 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4845 fstrcpy( src
->helpfile
, "" );
4848 /* are there any dependentfiles to examine? */
4850 if ( !src
->dependentfiles
)
4853 while ( *src
->dependentfiles
[i
] ) {
4854 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4856 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4857 trim_dependent_file( src
->dependentfiles
, i
);
4865 /****************************************************************************
4866 Determine whether or not a particular driver files are currently being
4867 used by any other driver.
4869 Return value is True if any files were in use by other drivers
4870 and False otherwise.
4872 Upon return, *info has been modified to only contain the driver files
4873 which are not in use
4874 ****************************************************************************/
4876 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4881 fstring
*list
= NULL
;
4882 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4887 version
= info
->cversion
;
4889 /* loop over all driver versions */
4891 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4893 /* get the list of drivers */
4896 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4898 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4899 ndrivers
, info
->environment
, version
));
4901 /* check each driver for overlap in files */
4903 for (i
=0; i
<ndrivers
; i
++) {
4904 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4906 ZERO_STRUCT(driver
);
4908 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4913 /* check if d2 uses any files from d1 */
4914 /* only if this is a different driver than the one being deleted */
4916 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4917 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4918 free_a_printer_driver(driver
, 3);
4924 free_a_printer_driver(driver
, 3);
4929 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4931 driver
.info_3
= info
;
4933 if ( DEBUGLEVEL
>= 20 )
4934 dump_a_printer_driver( driver
, 3 );
4939 /****************************************************************************
4940 Actually delete the driver files. Make sure that
4941 printer_driver_files_in_use() return False before calling
4943 ****************************************************************************/
4945 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4950 connection_struct
*conn
;
4960 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4963 * Connect to the print$ share under the same account as the
4964 * user connected to the rpc pipe. Note we must be root to
4968 null_pw
= data_blob( NULL
, 0 );
4969 fstrcpy(res_type
, "A:");
4971 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4975 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4979 /* Save who we are - we are temporarily becoming the connection user. */
4981 if ( !become_user(conn
, conn
->vuid
) ) {
4982 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4986 /* now delete the files; must strip the '\print$' string from
4989 if ( *info_3
->driverpath
) {
4990 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4992 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4993 DEBUG(10,("deleting driverfile [%s]\n", s
));
4994 unlink_internals(conn
, 0, file
);
4998 if ( *info_3
->configfile
) {
4999 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
5001 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
5002 DEBUG(10,("deleting configfile [%s]\n", s
));
5003 unlink_internals(conn
, 0, file
);
5007 if ( *info_3
->datafile
) {
5008 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
5010 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
5011 DEBUG(10,("deleting datafile [%s]\n", s
));
5012 unlink_internals(conn
, 0, file
);
5016 if ( *info_3
->helpfile
) {
5017 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
5019 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
5020 DEBUG(10,("deleting helpfile [%s]\n", s
));
5021 unlink_internals(conn
, 0, file
);
5025 /* check if we are done removing files */
5027 if ( info_3
->dependentfiles
) {
5028 while ( info_3
->dependentfiles
[i
][0] ) {
5031 /* bypass the "\print$" portion of the path */
5033 if ( (p
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
5035 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
5036 DEBUG(10,("deleting dependent file [%s]\n", file
));
5037 unlink_internals(conn
, 0, file
);
5049 /****************************************************************************
5050 Remove a printer driver from the TDB. This assumes that the the driver was
5051 previously looked up.
5052 ***************************************************************************/
5054 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
5055 uint32 version
, BOOL delete_files
)
5059 TDB_DATA kbuf
, dbuf
;
5060 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
5062 /* delete the tdb data first */
5064 arch
= get_short_archi(info_3
->environment
);
5065 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
5066 arch
, version
, info_3
->name
);
5068 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5069 key
, delete_files
? "TRUE" : "FALSE" ));
5071 ctr
.info_3
= info_3
;
5072 dump_a_printer_driver( ctr
, 3 );
5075 kbuf
.dsize
=strlen(key
)+1;
5077 /* check if the driver actually exists for this environment */
5079 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
5081 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
5082 return WERR_UNKNOWN_PRINTER_DRIVER
;
5085 SAFE_FREE( dbuf
.dptr
);
5087 /* ok... the driver exists so the delete should return success */
5089 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
5090 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
5091 return WERR_ACCESS_DENIED
;
5095 * now delete any associated files if delete_files == True
5096 * even if this part failes, we return succes because the
5097 * driver doesn not exist any more
5101 delete_driver_files( info_3
, user
);
5104 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
5109 /****************************************************************************
5110 Store a security desc for a printer.
5111 ****************************************************************************/
5113 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
5115 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5116 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
5118 TALLOC_CTX
*mem_ctx
= NULL
;
5122 mem_ctx
= talloc_init("nt_printing_setsec");
5123 if (mem_ctx
== NULL
)
5126 /* The old owner and group sids of the security descriptor are not
5127 present when new ACEs are added or removed by changing printer
5128 permissions through NT. If they are NULL in the new security
5129 descriptor then copy them over from the old one. */
5131 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
5132 DOM_SID
*owner_sid
, *group_sid
;
5133 SEC_ACL
*dacl
, *sacl
;
5134 SEC_DESC
*psd
= NULL
;
5137 nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
);
5139 /* Pick out correct owner and group sids */
5141 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
5142 secdesc_ctr
->sec
->owner_sid
:
5143 old_secdesc_ctr
->sec
->owner_sid
;
5145 group_sid
= secdesc_ctr
->sec
->grp_sid
?
5146 secdesc_ctr
->sec
->grp_sid
:
5147 old_secdesc_ctr
->sec
->grp_sid
;
5149 dacl
= secdesc_ctr
->sec
->dacl
?
5150 secdesc_ctr
->sec
->dacl
:
5151 old_secdesc_ctr
->sec
->dacl
;
5153 sacl
= secdesc_ctr
->sec
->sacl
?
5154 secdesc_ctr
->sec
->sacl
:
5155 old_secdesc_ctr
->sec
->sacl
;
5157 /* Make a deep copy of the security descriptor */
5159 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
5160 owner_sid
, group_sid
,
5165 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
5168 if (!new_secdesc_ctr
) {
5169 new_secdesc_ctr
= secdesc_ctr
;
5172 /* Store the security descriptor in a tdb */
5174 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
5175 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
5177 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
5179 status
= WERR_BADFUNC
;
5183 key
= make_printers_secdesc_tdbkey( sharename
);
5185 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
5188 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
5189 status
= WERR_BADFUNC
;
5192 /* Free malloc'ed memory */
5198 talloc_destroy(mem_ctx
);
5202 /****************************************************************************
5203 Construct a default security descriptor buffer for a printer.
5204 ****************************************************************************/
5206 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5208 SEC_ACE ace
[5]; /* max number of ace entries */
5211 SEC_ACL
*psa
= NULL
;
5212 SEC_DESC_BUF
*sdb
= NULL
;
5213 SEC_DESC
*psd
= NULL
;
5217 /* Create an ACE where Everyone is allowed to print */
5219 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
5220 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5221 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5223 /* Add the domain admins group if we are a DC */
5226 DOM_SID domadmins_sid
;
5228 sid_copy(&domadmins_sid
, get_global_sam_sid());
5229 sid_append_rid(&domadmins_sid
, DOMAIN_GROUP_RID_ADMINS
);
5231 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5232 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5233 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5234 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5235 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5236 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5238 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5239 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5241 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5242 init_sec_ace(&ace
[i
++], &adm_sid
,
5243 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5244 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5245 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5246 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5249 /* add BUILTIN\Administrators as FULL CONTROL */
5251 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5252 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5253 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5254 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5255 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5256 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5257 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5259 /* Make the security descriptor owned by the BUILTIN\Administrators */
5261 /* The ACL revision number in rpc_secdesc.h differs from the one
5262 created by NT when setting ACE entries in printer
5263 descriptors. NT4 complains about the property being edited by a
5266 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5267 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5268 &global_sid_Builtin_Administrators
,
5269 &global_sid_Builtin_Administrators
,
5270 NULL
, psa
, &sd_size
);
5274 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5278 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5280 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5281 (unsigned int)sd_size
));
5286 /****************************************************************************
5287 Get a security desc for a printer.
5288 ****************************************************************************/
5290 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5296 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5297 sharename
= temp
+ 1;
5300 /* Fetch security descriptor from tdb */
5302 key
= make_printers_secdesc_tdbkey( sharename
);
5304 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
5305 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5307 DEBUG(4,("using default secdesc for %s\n", sharename
));
5309 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
5313 /* Save default security descriptor for later */
5315 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
5316 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
5318 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
5319 tdb_prs_store(tdb_printers
, key
, &ps
);
5326 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5327 this security descriptor has been created when winbindd was
5328 down. Take ownership of security descriptor. */
5330 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
5333 /* Change sd owner to workgroup administrator */
5335 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5336 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5337 SEC_DESC
*psd
= NULL
;
5342 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5344 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
5346 (*secdesc_ctr
)->sec
->grp_sid
,
5347 (*secdesc_ctr
)->sec
->sacl
,
5348 (*secdesc_ctr
)->sec
->dacl
,
5351 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5353 /* Swap with other one */
5355 *secdesc_ctr
= new_secdesc_ctr
;
5359 nt_printing_setsec(sharename
, *secdesc_ctr
);
5363 if (DEBUGLEVEL
>= 10) {
5364 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
5367 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5368 sharename
, the_acl
->num_aces
));
5370 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5373 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5375 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
5376 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
5377 the_acl
->ace
[i
].info
.mask
));
5387 1: level not implemented
5388 2: file doesn't exist
5389 3: can't allocate memory
5390 4: can't free memory
5391 5: non existant struct
5395 A printer and a printer driver are 2 different things.
5396 NT manages them separatelly, Samba does the same.
5397 Why ? Simply because it's easier and it makes sense !
5399 Now explanation: You have 3 printers behind your samba server,
5400 2 of them are the same make and model (laser A and B). But laser B
5401 has an 3000 sheet feeder and laser A doesn't such an option.
5402 Your third printer is an old dot-matrix model for the accounting :-).
5404 If the /usr/local/samba/lib directory (default dir), you will have
5405 5 files to describe all of this.
5407 3 files for the printers (1 by printer):
5410 NTprinter_accounting
5411 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5412 NTdriver_printer model X
5413 NTdriver_printer model Y
5415 jfm: I should use this comment for the text file to explain
5416 same thing for the forms BTW.
5417 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5421 /* Convert generic access rights to printer object specific access rights.
5422 It turns out that NT4 security descriptors use generic access rights and
5423 NT5 the object specific ones. */
5425 void map_printer_permissions(SEC_DESC
*sd
)
5429 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5430 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
5431 &printer_generic_mapping
);
5435 /****************************************************************************
5436 Check a user has permissions to perform the given operation. We use the
5437 permission constants defined in include/rpc_spoolss.h to check the various
5438 actions we perform when checking printer access.
5440 PRINTER_ACCESS_ADMINISTER:
5441 print_queue_pause, print_queue_resume, update_printer_sec,
5442 update_printer, spoolss_addprinterex_level_2,
5443 _spoolss_setprinterdata
5448 JOB_ACCESS_ADMINISTER:
5449 print_job_delete, print_job_pause, print_job_resume,
5452 Try access control in the following order (for performance reasons):
5453 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5454 2) check security descriptor (bit comparisons in memory)
5455 3) "printer admins" (may result in numerous calls to winbind)
5457 ****************************************************************************/
5458 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5460 SEC_DESC_BUF
*secdesc
= NULL
;
5461 uint32 access_granted
;
5465 TALLOC_CTX
*mem_ctx
= NULL
;
5466 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5468 /* If user is NULL then use the current_user structure */
5471 user
= ¤t_user
;
5473 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5475 if ( user
->uid
== 0 || user_has_privileges(user
->nt_user_token
, &se_printop
) ) {
5479 /* Get printer name */
5481 pname
= PRINTERNAME(snum
);
5483 if (!pname
|| !*pname
) {
5488 /* Get printer security descriptor */
5490 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5495 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
5497 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5498 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5500 /* Create a child security descriptor to check permissions
5501 against. This is because print jobs are child objects
5502 objects of a printer. */
5504 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
5506 /* Now this is the bit that really confuses me. The access
5507 type needs to be changed from JOB_ACCESS_ADMINISTER to
5508 PRINTER_ACCESS_ADMINISTER for this to work. Something
5509 to do with the child (job) object becoming like a
5512 access_type
= PRINTER_ACCESS_ADMINISTER
;
5517 map_printer_permissions(secdesc
->sec
);
5519 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
5520 &access_granted
, &status
);
5522 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5524 /* see if we need to try the printer admin list */
5526 if ( access_granted
== 0 ) {
5527 if ( user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
) )
5531 talloc_destroy(mem_ctx
);
5539 /****************************************************************************
5540 Check the time parameters allow a print operation.
5541 *****************************************************************************/
5543 BOOL
print_time_access_check(int snum
)
5545 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5547 time_t now
= time(NULL
);
5551 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5554 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5558 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5560 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5563 free_a_printer(&printer
, 2);
5571 /****************************************************************************
5572 Fill in the servername sent in the _spoolss_open_printer_ex() call
5573 ****************************************************************************/
5575 char* get_server_name( Printer_entry
*printer
)
5577 return printer
->servername
;