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 /* of course, none of the message callbacks matter if you don't
621 tell messages.c that you interested in receiving PRINT_GENERAL
622 msgs. This is done in claim_connection() */
625 if ( lp_security() == SEC_ADS
) {
626 win_rc
= check_published_printers();
627 if (!W_ERROR_IS_OK(win_rc
))
628 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
634 /*******************************************************************
635 Function to allow filename parsing "the old way".
636 ********************************************************************/
638 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
639 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
642 unix_clean_name(name
);
643 trim_string(name
,"/","/");
644 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
647 /*******************************************************************
648 tdb traversal function for counting printers.
649 ********************************************************************/
651 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
652 TDB_DATA data
, void *context
)
654 int *printer_count
= (int*)context
;
656 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
658 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
664 /*******************************************************************
665 Update the spooler global c_setprinter. This variable is initialized
666 when the parent smbd starts with the number of existing printers. It
667 is monotonically increased by the current number of printers *after*
668 each add or delete printer RPC. Only Microsoft knows why... JRR020119
669 ********************************************************************/
671 uint32
update_c_setprinter(BOOL initialize
)
674 int32 printer_count
= 0;
676 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
678 /* Traverse the tdb, counting the printers */
679 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
681 /* If initializing, set c_setprinter to current printers count
682 * otherwise, bump it by the current printer count
685 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
687 c_setprinter
= printer_count
;
689 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
690 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
692 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
694 return (uint32
)c_setprinter
;
697 /*******************************************************************
698 Get the spooler global c_setprinter, accounting for initialization.
699 ********************************************************************/
701 uint32
get_c_setprinter(void)
703 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
705 if (c_setprinter
== (int32
)-1)
706 c_setprinter
= update_c_setprinter(True
);
708 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
710 return (uint32
)c_setprinter
;
713 /****************************************************************************
714 Get builtin form struct list.
715 ****************************************************************************/
717 int get_builtin_ntforms(nt_forms_struct
**list
)
719 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
720 return sizeof(default_forms
) / sizeof(default_forms
[0]);
723 /****************************************************************************
724 get a builtin form struct
725 ****************************************************************************/
727 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
731 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
732 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
733 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
734 for (i
=0;i
<count
;i
++) {
735 if (strequal(form_name
,default_forms
[i
].name
)) {
736 DEBUGADD(6,("Found builtin form %s \n", form_name
));
737 memcpy(form
,&default_forms
[i
],sizeof(*form
));
745 /****************************************************************************
746 get a form struct list.
747 ****************************************************************************/
749 int get_ntforms(nt_forms_struct
**list
)
751 TDB_DATA kbuf
, newkey
, dbuf
;
752 nt_forms_struct form
;
759 for (kbuf
= tdb_firstkey(tdb_forms
);
761 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
763 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
766 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
770 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
771 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
772 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
773 &form
.top
, &form
.right
, &form
.bottom
);
774 SAFE_FREE(dbuf
.dptr
);
775 if (ret
!= dbuf
.dsize
)
778 *list
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
780 DEBUG(0,("get_ntforms: Realloc fail.\n"));
791 /****************************************************************************
792 write a form struct list
793 ****************************************************************************/
794 int write_ntforms(nt_forms_struct
**list
, int number
)
801 for (i
=0;i
<number
;i
++) {
802 /* save index, so list is rebuilt in correct order */
803 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
804 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
805 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
807 if (len
> sizeof(buf
)) break;
808 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
809 kbuf
.dsize
= strlen(key
)+1;
813 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
819 /****************************************************************************
820 add a form struct at the end of the list
821 ****************************************************************************/
822 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
829 * NT tries to add forms even when
830 * they are already in the base
831 * only update the values if already present
836 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
837 for (n
=0; n
<*count
; n
++) {
838 if ( strequal((*list
)[n
].name
, form_name
) ) {
845 if((*list
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
846 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
849 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
853 (*list
)[n
].flag
=form
->flags
;
854 (*list
)[n
].width
=form
->size_x
;
855 (*list
)[n
].length
=form
->size_y
;
856 (*list
)[n
].left
=form
->left
;
857 (*list
)[n
].top
=form
->top
;
858 (*list
)[n
].right
=form
->right
;
859 (*list
)[n
].bottom
=form
->bottom
;
861 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
862 update
? "updated" : "added", form_name
));
867 /****************************************************************************
868 Delete a named form struct.
869 ****************************************************************************/
871 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
880 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
882 for (n
=0; n
<*count
; n
++) {
883 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
884 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
890 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
891 *ret
= WERR_INVALID_PARAM
;
895 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
896 kbuf
.dsize
= strlen(key
)+1;
898 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
906 /****************************************************************************
907 Update a form struct.
908 ****************************************************************************/
910 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
914 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
916 DEBUG(106, ("[%s]\n", form_name
));
917 for (n
=0; n
<count
; n
++) {
918 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
919 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
923 if (n
==count
) return;
925 (*list
)[n
].flag
=form
->flags
;
926 (*list
)[n
].width
=form
->size_x
;
927 (*list
)[n
].length
=form
->size_y
;
928 (*list
)[n
].left
=form
->left
;
929 (*list
)[n
].top
=form
->top
;
930 (*list
)[n
].right
=form
->right
;
931 (*list
)[n
].bottom
=form
->bottom
;
934 /****************************************************************************
935 Get the nt drivers list.
936 Traverse the database and look-up the matching names.
937 ****************************************************************************/
938 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
941 const char *short_archi
;
943 TDB_DATA kbuf
, newkey
;
945 short_archi
= get_short_archi(architecture
);
946 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
948 for (kbuf
= tdb_firstkey(tdb_drivers
);
950 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
952 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
955 if((*list
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
956 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
960 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
967 /****************************************************************************
968 function to do the mapping between the long architecture name and
970 ****************************************************************************/
971 const char *get_short_archi(const char *long_archi
)
975 DEBUG(107,("Getting architecture dependant directory\n"));
978 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
979 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
981 if (archi_table
[i
].long_archi
==NULL
) {
982 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
986 /* this might be client code - but shouldn't this be an fstrcpy etc? */
989 DEBUGADD(108,("index: [%d]\n", i
));
990 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
991 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
993 return archi_table
[i
].short_archi
;
996 /****************************************************************************
997 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
998 There are two case to be covered here: PE (Portable Executable) and NE (New
999 Executable) files. Both files support the same INFO structure, but PE files
1000 store the signature in unicode, and NE files store it as !unicode.
1001 returns -1 on error, 1 on version info found, and 0 on no version info found.
1002 ****************************************************************************/
1004 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1010 if ((buf
=SMB_MALLOC(PE_HEADER_SIZE
)) == NULL
) {
1011 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1012 fname
, PE_HEADER_SIZE
));
1016 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1017 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1018 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1019 fname
, (unsigned long)byte_count
));
1020 goto no_version_info
;
1023 /* Is this really a DOS header? */
1024 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1025 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1026 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1027 goto no_version_info
;
1030 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1031 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1032 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1034 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1035 goto no_version_info
;
1038 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
1039 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1040 fname
, (unsigned long)byte_count
));
1041 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1042 goto no_version_info
;
1045 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1046 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1047 unsigned int num_sections
;
1048 unsigned int section_table_bytes
;
1050 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
1051 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1052 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
1053 /* At this point, we assume the file is in error. It still could be somthing
1054 * else besides a PE file, but it unlikely at this point.
1059 /* get the section table */
1060 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1061 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1062 if (section_table_bytes
== 0)
1066 if ((buf
=SMB_MALLOC(section_table_bytes
)) == NULL
) {
1067 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1068 fname
, section_table_bytes
));
1072 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1073 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1074 fname
, (unsigned long)byte_count
));
1078 /* Iterate the section table looking for the resource section ".rsrc" */
1079 for (i
= 0; i
< num_sections
; i
++) {
1080 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1082 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1083 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1084 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1086 if (section_bytes
== 0)
1090 if ((buf
=SMB_MALLOC(section_bytes
)) == NULL
) {
1091 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1092 fname
, section_bytes
));
1096 /* Seek to the start of the .rsrc section info */
1097 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1098 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1103 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1104 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1105 fname
, (unsigned long)byte_count
));
1109 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1112 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1113 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1114 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1115 /* Align to next long address */
1116 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1118 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1119 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1120 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1122 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1123 fname
, *major
, *minor
,
1124 (*major
>>16)&0xffff, *major
&0xffff,
1125 (*minor
>>16)&0xffff, *minor
&0xffff));
1134 /* Version info not found, fall back to origin date/time */
1135 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1139 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1140 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1141 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1142 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1143 /* At this point, we assume the file is in error. It still could be somthing
1144 * else besides a NE file, but it unlikely at this point. */
1148 /* Allocate a bit more space to speed up things */
1150 if ((buf
=SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1151 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1152 fname
, PE_HEADER_SIZE
));
1156 /* This is a HACK! I got tired of trying to sort through the messy
1157 * 'NE' file format. If anyone wants to clean this up please have at
1158 * it, but this works. 'NE' files will eventually fade away. JRR */
1159 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1160 /* Cover case that should not occur in a well formed 'NE' .dll file */
1161 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1163 for(i
=0; i
<byte_count
; i
++) {
1164 /* Fast skip past data that can't possibly match */
1165 if (buf
[i
] != 'V') continue;
1167 /* Potential match data crosses buf boundry, move it to beginning
1168 * of buf, and fill the buf with as much as it will hold. */
1169 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1172 memcpy(buf
, &buf
[i
], byte_count
-i
);
1173 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1174 (byte_count
-i
))) < 0) {
1176 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1181 byte_count
= bc
+ (byte_count
- i
);
1182 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1187 /* Check that the full signature string and the magic number that
1188 * follows exist (not a perfect solution, but the chances that this
1189 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1190 * twice, as it is simpler to read the code. */
1191 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1192 /* Compute skip alignment to next long address */
1193 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
1194 sizeof(VS_SIGNATURE
)) & 3;
1195 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1197 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1198 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1199 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1200 fname
, *major
, *minor
,
1201 (*major
>>16)&0xffff, *major
&0xffff,
1202 (*minor
>>16)&0xffff, *minor
&0xffff));
1209 /* Version info not found, fall back to origin date/time */
1210 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1215 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1216 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1217 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1228 /****************************************************************************
1229 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1230 share one or more files. During the MS installation process files are checked
1231 to insure that only a newer version of a shared file is installed over an
1232 older version. There are several possibilities for this comparison. If there
1233 is no previous version, the new one is newer (obviously). If either file is
1234 missing the version info structure, compare the creation date (on Unix use
1235 the modification date). Otherwise chose the numerically larger version number.
1236 ****************************************************************************/
1238 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1240 BOOL use_version
= True
;
1245 time_t new_create_time
;
1249 time_t old_create_time
;
1251 files_struct
*fsp
= NULL
;
1253 SMB_STRUCT_STAT stat_buf
;
1256 SET_STAT_INVALID(st
);
1257 SET_STAT_INVALID(stat_buf
);
1258 new_create_time
= (time_t)0;
1259 old_create_time
= (time_t)0;
1261 /* Get file version info (if available) for previous file (if it exists) */
1262 pstrcpy(filepath
, old_file
);
1264 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1266 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1268 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1271 FILE_ATTRIBUTE_NORMAL
,
1276 /* Old file not found, so by definition new file is in fact newer */
1277 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1282 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1288 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1290 use_version
= False
;
1291 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1292 old_create_time
= st
.st_mtime
;
1293 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1296 close_file(fsp
, NORMAL_CLOSE
);
1298 /* Get file version info (if available) for new file */
1299 pstrcpy(filepath
, new_file
);
1300 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1302 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1304 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1307 FILE_ATTRIBUTE_NORMAL
,
1312 /* New file not found, this shouldn't occur if the caller did its job */
1313 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1318 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1324 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1326 use_version
= False
;
1327 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1328 new_create_time
= st
.st_mtime
;
1329 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1332 close_file(fsp
, NORMAL_CLOSE
);
1334 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1335 /* Compare versions and choose the larger version number */
1336 if (new_major
> old_major
||
1337 (new_major
== old_major
&& new_minor
> old_minor
)) {
1339 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1343 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1348 /* Compare modification time/dates and choose the newest time/date */
1349 if (new_create_time
> old_create_time
) {
1350 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1354 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1361 close_file(fsp
, NORMAL_CLOSE
);
1365 /****************************************************************************
1366 Determine the correct cVersion associated with an architecture and driver
1367 ****************************************************************************/
1368 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1369 struct current_user
*user
, WERROR
*perr
)
1376 files_struct
*fsp
= NULL
;
1379 connection_struct
*conn
;
1381 SET_STAT_INVALID(st
);
1383 *perr
= WERR_INVALID_PARAM
;
1385 /* If architecture is Windows 95/98/ME, the version is always 0. */
1386 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1387 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1392 /* If architecture is Windows x64, the version is always 3. */
1393 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1394 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1400 * Connect to the print$ share under the same account as the user connected
1401 * to the rpc pipe. Note we must still be root to do this.
1404 /* Null password is ok - we are already an authenticated user... */
1405 null_pw
= data_blob(NULL
, 0);
1406 fstrcpy(res_type
, "A:");
1408 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1412 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1413 *perr
= ntstatus_to_werror(nt_status
);
1417 /* We are temporarily becoming the connection user. */
1418 if (!become_user(conn
, user
->vuid
)) {
1419 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1420 *perr
= WERR_ACCESS_DENIED
;
1424 /* Open the driver file (Portable Executable format) and determine the
1425 * deriver the cversion. */
1426 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1428 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1430 if ( !vfs_file_exist( conn
, driverpath
, &st
) ) {
1431 *perr
= WERR_BADFILE
;
1435 fsp
= open_file_ntcreate(conn
, driverpath
, &st
,
1437 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1440 FILE_ATTRIBUTE_NORMAL
,
1445 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1446 driverpath
, errno
));
1447 *perr
= WERR_ACCESS_DENIED
;
1452 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1453 if (ret
== -1) goto error_exit
;
1456 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1461 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1462 * for more details. Version in this case is not just the version of the
1463 * file, but the version in the sense of kernal mode (2) vs. user mode
1464 * (3) drivers. Other bits of the version fields are the version info.
1467 cversion
= major
& 0x0000ffff;
1469 case 2: /* WinNT drivers */
1470 case 3: /* Win2K drivers */
1474 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1475 driverpath
, cversion
));
1479 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1480 driverpath
, major
, minor
));
1483 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1484 driverpath
, cversion
));
1486 close_file(fsp
, NORMAL_CLOSE
);
1487 close_cnum(conn
, user
->vuid
);
1496 close_file(fsp
, NORMAL_CLOSE
);
1498 close_cnum(conn
, user
->vuid
);
1503 /****************************************************************************
1504 ****************************************************************************/
1505 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1506 struct current_user
*user
)
1508 const char *architecture
;
1514 /* clean up the driver name.
1515 * we can get .\driver.dll
1516 * or worse c:\windows\system\driver.dll !
1518 /* using an intermediate string to not have overlaping memcpy()'s */
1519 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1520 fstrcpy(new_name
, p
+1);
1521 fstrcpy(driver
->driverpath
, new_name
);
1524 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1525 fstrcpy(new_name
, p
+1);
1526 fstrcpy(driver
->datafile
, new_name
);
1529 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1530 fstrcpy(new_name
, p
+1);
1531 fstrcpy(driver
->configfile
, new_name
);
1534 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1535 fstrcpy(new_name
, p
+1);
1536 fstrcpy(driver
->helpfile
, new_name
);
1539 if (driver
->dependentfiles
) {
1540 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1541 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1542 fstrcpy(new_name
, p
+1);
1543 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1548 architecture
= get_short_archi(driver
->environment
);
1550 /* jfm:7/16/2000 the client always sends the cversion=0.
1551 * The server should check which version the driver is by reading
1552 * the PE header of driver->driverpath.
1554 * For Windows 95/98 the version is 0 (so the value sent is correct)
1555 * For Windows NT (the architecture doesn't matter)
1556 * NT 3.1: cversion=0
1557 * NT 3.5/3.51: cversion=1
1561 if ((driver
->cversion
= get_correct_cversion( architecture
, driver
->driverpath
, user
, &err
)) == -1)
1567 /****************************************************************************
1568 ****************************************************************************/
1569 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1571 const char *architecture
;
1577 /* clean up the driver name.
1578 * we can get .\driver.dll
1579 * or worse c:\windows\system\driver.dll !
1581 /* using an intermediate string to not have overlaping memcpy()'s */
1582 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1583 fstrcpy(new_name
, p
+1);
1584 fstrcpy(driver
->driverpath
, new_name
);
1587 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1588 fstrcpy(new_name
, p
+1);
1589 fstrcpy(driver
->datafile
, new_name
);
1592 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1593 fstrcpy(new_name
, p
+1);
1594 fstrcpy(driver
->configfile
, new_name
);
1597 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1598 fstrcpy(new_name
, p
+1);
1599 fstrcpy(driver
->helpfile
, new_name
);
1602 if (driver
->dependentfiles
) {
1603 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1604 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1605 fstrcpy(new_name
, p
+1);
1606 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1611 architecture
= get_short_archi(driver
->environment
);
1613 /* jfm:7/16/2000 the client always sends the cversion=0.
1614 * The server should check which version the driver is by reading
1615 * the PE header of driver->driverpath.
1617 * For Windows 95/98 the version is 0 (so the value sent is correct)
1618 * For Windows NT (the architecture doesn't matter)
1619 * NT 3.1: cversion=0
1620 * NT 3.5/3.51: cversion=1
1625 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1631 /****************************************************************************
1632 ****************************************************************************/
1633 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1634 uint32 level
, struct current_user
*user
)
1639 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1640 driver
=driver_abstract
.info_3
;
1641 return clean_up_driver_struct_level_3(driver
, user
);
1645 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1646 driver
=driver_abstract
.info_6
;
1647 return clean_up_driver_struct_level_6(driver
, user
);
1650 return WERR_INVALID_PARAM
;
1654 /****************************************************************************
1655 This function sucks and should be replaced. JRA.
1656 ****************************************************************************/
1658 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1660 dst
->cversion
= src
->version
;
1662 fstrcpy( dst
->name
, src
->name
);
1663 fstrcpy( dst
->environment
, src
->environment
);
1664 fstrcpy( dst
->driverpath
, src
->driverpath
);
1665 fstrcpy( dst
->datafile
, src
->datafile
);
1666 fstrcpy( dst
->configfile
, src
->configfile
);
1667 fstrcpy( dst
->helpfile
, src
->helpfile
);
1668 fstrcpy( dst
->monitorname
, src
->monitorname
);
1669 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1670 dst
->dependentfiles
= src
->dependentfiles
;
1673 #if 0 /* Debugging function */
1675 static char* ffmt(unsigned char *c
){
1677 static char ffmt_str
[17];
1679 for (i
=0; i
<16; i
++) {
1680 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1691 /****************************************************************************
1692 ****************************************************************************/
1693 WERROR
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1694 struct current_user
*user
, WERROR
*perr
)
1696 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1697 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1698 const char *architecture
;
1703 connection_struct
*conn
;
1714 memset(inbuf
, '\0', sizeof(inbuf
));
1715 memset(outbuf
, '\0', sizeof(outbuf
));
1719 driver
=driver_abstract
.info_3
;
1720 else if (level
==6) {
1721 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1722 driver
= &converted_driver
;
1724 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1725 return WERR_UNKNOWN_LEVEL
;
1728 architecture
= get_short_archi(driver
->environment
);
1731 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1732 * Note we must be root to do this.
1735 null_pw
= data_blob(NULL
, 0);
1736 fstrcpy(res_type
, "A:");
1738 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1742 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1743 *perr
= ntstatus_to_werror(nt_status
);
1744 return WERR_NO_SUCH_SHARE
;
1748 * Save who we are - we are temporarily becoming the connection user.
1751 if (!become_user(conn
, conn
->vuid
)) {
1752 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1753 return WERR_ACCESS_DENIED
;
1757 * make the directories version and version\driver_name
1758 * under the architecture directory.
1760 DEBUG(5,("Creating first directory\n"));
1761 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1762 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1763 mkdir_internal(conn
, new_dir
, bad_path
);
1765 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1766 * listed for this driver which has already been moved, skip it (note:
1767 * drivers may list the same file name several times. Then check if the
1768 * file already exists in archi\cversion\, if so, check that the version
1769 * info (or time stamps if version info is unavailable) is newer (or the
1770 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1771 * Otherwise, delete the file.
1773 * If a file is not moved to archi\cversion\ because of an error, all the
1774 * rest of the 'unmoved' driver files are removed from archi\. If one or
1775 * more of the driver's files was already moved to archi\cversion\, it
1776 * potentially leaves the driver in a partially updated state. Version
1777 * trauma will most likely occur if an client attempts to use any printer
1778 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1779 * done is appropriate... later JRR
1782 DEBUG(5,("Moving files now !\n"));
1784 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1785 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1786 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1787 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1788 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1789 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1790 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1791 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1792 new_name
, old_name
));
1793 *perr
= WERR_ACCESS_DENIED
;
1799 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1800 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1801 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1802 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1803 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1804 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1805 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1806 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1807 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1808 new_name
, old_name
));
1809 *perr
= WERR_ACCESS_DENIED
;
1816 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1817 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1818 !strequal(driver
->configfile
, driver
->datafile
)) {
1819 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1820 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1821 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1822 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1823 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1824 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1825 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1826 new_name
, old_name
));
1827 *perr
= WERR_ACCESS_DENIED
;
1834 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1835 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1836 !strequal(driver
->helpfile
, driver
->datafile
) &&
1837 !strequal(driver
->helpfile
, driver
->configfile
)) {
1838 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1839 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1840 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1841 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1842 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1843 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1844 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1845 new_name
, old_name
));
1846 *perr
= WERR_ACCESS_DENIED
;
1853 if (driver
->dependentfiles
) {
1854 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1855 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1856 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1857 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1858 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1860 for (j
=0; j
< i
; j
++) {
1861 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1866 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1867 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1868 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1869 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1870 if ( !copy_file(new_name
, old_name
, conn
,
1871 OPENX_FILE_EXISTS_TRUNCATE
|
1872 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1873 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1874 new_name
, old_name
));
1875 *perr
= WERR_ACCESS_DENIED
;
1884 close_cnum(conn
, user
->vuid
);
1887 return ver
!= -1 ? WERR_OK
: WERR_UNKNOWN_PRINTER_DRIVER
;
1890 /****************************************************************************
1891 ****************************************************************************/
1892 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1895 const char *architecture
;
1901 TDB_DATA kbuf
, dbuf
;
1903 architecture
= get_short_archi(driver
->environment
);
1905 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1906 * \\server is added in the rpc server layer.
1907 * It does make sense to NOT store the server's name in the printer TDB.
1910 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1912 /* .inf files do not always list a file for each of the four standard files.
1913 * Don't prepend a path to a null filename, or client claims:
1914 * "The server on which the printer resides does not have a suitable
1915 * <printer driver name> printer driver installed. Click OK if you
1916 * wish to install the driver on your local machine."
1918 if (strlen(driver
->driverpath
)) {
1919 fstrcpy(temp_name
, driver
->driverpath
);
1920 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1923 if (strlen(driver
->datafile
)) {
1924 fstrcpy(temp_name
, driver
->datafile
);
1925 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1928 if (strlen(driver
->configfile
)) {
1929 fstrcpy(temp_name
, driver
->configfile
);
1930 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1933 if (strlen(driver
->helpfile
)) {
1934 fstrcpy(temp_name
, driver
->helpfile
);
1935 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1938 if (driver
->dependentfiles
) {
1939 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1940 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1941 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1945 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1947 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1954 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1957 driver
->environment
,
1962 driver
->monitorname
,
1963 driver
->defaultdatatype
);
1965 if (driver
->dependentfiles
) {
1966 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1967 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1968 driver
->dependentfiles
[i
]);
1972 if (len
!= buflen
) {
1973 buf
= (char *)SMB_REALLOC(buf
, len
);
1975 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1985 kbuf
.dsize
= strlen(key
)+1;
1989 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1993 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1999 /****************************************************************************
2000 ****************************************************************************/
2001 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
2003 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
2006 info3
.cversion
= driver
->version
;
2007 fstrcpy(info3
.name
,driver
->name
);
2008 fstrcpy(info3
.environment
,driver
->environment
);
2009 fstrcpy(info3
.driverpath
,driver
->driverpath
);
2010 fstrcpy(info3
.datafile
,driver
->datafile
);
2011 fstrcpy(info3
.configfile
,driver
->configfile
);
2012 fstrcpy(info3
.helpfile
,driver
->helpfile
);
2013 fstrcpy(info3
.monitorname
,driver
->monitorname
);
2014 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
2015 info3
.dependentfiles
= driver
->dependentfiles
;
2017 return add_a_printer_driver_3(&info3
);
2021 /****************************************************************************
2022 ****************************************************************************/
2023 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
2025 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
2029 fstrcpy(info
.name
, driver
);
2030 fstrcpy(info
.defaultdatatype
, "RAW");
2032 fstrcpy(info
.driverpath
, "");
2033 fstrcpy(info
.datafile
, "");
2034 fstrcpy(info
.configfile
, "");
2035 fstrcpy(info
.helpfile
, "");
2037 if ((info
.dependentfiles
= SMB_MALLOC_ARRAY(fstring
, 2)) == NULL
)
2040 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
2041 fstrcpy(info
.dependentfiles
[0], "");
2043 *info_ptr
= memdup(&info
, sizeof(info
));
2048 /****************************************************************************
2049 ****************************************************************************/
2050 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
2052 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
2053 TDB_DATA kbuf
, dbuf
;
2054 const char *architecture
;
2059 ZERO_STRUCT(driver
);
2061 architecture
= get_short_archi(arch
);
2063 if ( !architecture
)
2064 return WERR_UNKNOWN_PRINTER_DRIVER
;
2066 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2068 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2071 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2073 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
2076 kbuf
.dsize
= strlen(key
)+1;
2078 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
2080 return WERR_UNKNOWN_PRINTER_DRIVER
;
2082 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2091 driver
.defaultdatatype
);
2094 while (len
< dbuf
.dsize
) {
2095 driver
.dependentfiles
= SMB_REALLOC_ARRAY(driver
.dependentfiles
, fstring
, i
+2);
2096 if ( !driver
.dependentfiles
) {
2097 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2101 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2102 &driver
.dependentfiles
[i
]);
2106 if ( driver
.dependentfiles
)
2107 fstrcpy( driver
.dependentfiles
[i
], "" );
2109 SAFE_FREE(dbuf
.dptr
);
2111 if (len
!= dbuf
.dsize
) {
2112 SAFE_FREE(driver
.dependentfiles
);
2114 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
2117 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
2122 /****************************************************************************
2123 Debugging function, dump at level 6 the struct in the logs.
2124 ****************************************************************************/
2126 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2129 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
2132 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
2138 if (driver
.info_3
== NULL
)
2141 info3
=driver
.info_3
;
2143 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
2144 DEBUGADD(20,("name:[%s]\n", info3
->name
));
2145 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
2146 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
2147 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
2148 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
2149 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
2150 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
2151 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
2153 for (i
=0; info3
->dependentfiles
&&
2154 *info3
->dependentfiles
[i
]; i
++) {
2155 DEBUGADD(20,("dependentfile:[%s]\n",
2156 info3
->dependentfiles
[i
]));
2163 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
2171 /****************************************************************************
2172 ****************************************************************************/
2173 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
2177 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2182 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2183 nt_devmode
->devicename
,
2184 nt_devmode
->formname
,
2186 nt_devmode
->specversion
,
2187 nt_devmode
->driverversion
,
2189 nt_devmode
->driverextra
,
2190 nt_devmode
->orientation
,
2191 nt_devmode
->papersize
,
2192 nt_devmode
->paperlength
,
2193 nt_devmode
->paperwidth
,
2196 nt_devmode
->defaultsource
,
2197 nt_devmode
->printquality
,
2200 nt_devmode
->yresolution
,
2201 nt_devmode
->ttoption
,
2202 nt_devmode
->collate
,
2203 nt_devmode
->logpixels
,
2206 nt_devmode
->bitsperpel
,
2207 nt_devmode
->pelswidth
,
2208 nt_devmode
->pelsheight
,
2209 nt_devmode
->displayflags
,
2210 nt_devmode
->displayfrequency
,
2211 nt_devmode
->icmmethod
,
2212 nt_devmode
->icmintent
,
2213 nt_devmode
->mediatype
,
2214 nt_devmode
->dithertype
,
2215 nt_devmode
->reserved1
,
2216 nt_devmode
->reserved2
,
2217 nt_devmode
->panningwidth
,
2218 nt_devmode
->panningheight
,
2219 nt_devmode
->nt_dev_private
);
2222 if (nt_devmode
->nt_dev_private
) {
2223 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2224 nt_devmode
->driverextra
,
2225 nt_devmode
->nt_dev_private
);
2228 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2233 /****************************************************************************
2234 Pack all values in all printer keys
2235 ***************************************************************************/
2237 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2241 REGISTRY_VALUE
*val
;
2242 REGVAL_CTR
*val_ctr
;
2249 /* loop over all keys */
2251 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2252 val_ctr
= data
->keys
[i
].values
;
2253 num_values
= regval_ctr_numvals( val_ctr
);
2255 /* pack the keyname followed by a empty value */
2257 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2258 &data
->keys
[i
].name
,
2264 /* now loop over all values */
2266 for ( j
=0; j
<num_values
; j
++ ) {
2267 /* pathname should be stored as <key>\<value> */
2269 val
= regval_ctr_specific_value( val_ctr
, j
);
2270 pstrcpy( path
, data
->keys
[i
].name
);
2271 pstrcat( path
, "\\" );
2272 pstrcat( path
, regval_name(val
) );
2274 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2279 regval_data_p(val
) );
2281 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2288 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2294 /****************************************************************************
2295 Delete a printer - this just deletes the printer info file, any open
2296 handles are not affected.
2297 ****************************************************************************/
2299 uint32
del_a_printer(const char *sharename
)
2303 pstring printdb_path
;
2305 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2307 kbuf
.dsize
=strlen(key
)+1;
2308 tdb_delete(tdb_printers
, kbuf
);
2310 slprintf(key
, sizeof(key
)-1, "%s%s", SECDESC_PREFIX
, sharename
);
2312 kbuf
.dsize
=strlen(key
)+1;
2313 tdb_delete(tdb_printers
, kbuf
);
2315 close_all_print_db();
2317 if (geteuid() == 0) {
2318 pstrcpy(printdb_path
, lock_path("printing/"));
2319 pstrcat(printdb_path
, sharename
);
2320 pstrcat(printdb_path
, ".tdb");
2322 unlink(printdb_path
);
2328 /****************************************************************************
2329 ****************************************************************************/
2330 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2335 TDB_DATA kbuf
, dbuf
;
2338 * in addprinter: no servername and the printer is the name
2339 * in setprinter: servername is \\server
2340 * and printer is \\server\\printer
2342 * Samba manages only local printers.
2343 * we currently don't support things like i
2344 * path=\\other_server\printer
2346 * We only store the printername, not \\server\printername
2349 if ( info
->servername
[0] != '\0' ) {
2350 trim_string(info
->printername
, info
->servername
, NULL
);
2351 trim_char(info
->printername
, '\\', '\0');
2352 info
->servername
[0]='\0';
2356 * JFM: one day I'll forget.
2357 * below that's info->portname because that's the SAMBA sharename
2358 * and I made NT 'thinks' it's the portname
2359 * the info->sharename is the thing you can name when you add a printer
2360 * that's the short-name when you create shared printer for 95/98
2361 * So I've made a limitation in SAMBA: you can only have 1 printer model
2362 * behind a SAMBA share.
2370 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2373 info
->default_priority
,
2390 info
->printprocessor
,
2394 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2396 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
2398 if (buflen
!= len
) {
2399 buf
= (char *)SMB_REALLOC(buf
, len
);
2401 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2410 kbuf
= make_printer_tdbkey( info
->sharename
);
2415 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2418 if (!W_ERROR_IS_OK(ret
))
2419 DEBUG(8, ("error updating printer to tdb on disk\n"));
2423 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2424 info
->sharename
, info
->drivername
, info
->portname
, len
));
2430 /****************************************************************************
2431 Malloc and return an NT devicemode.
2432 ****************************************************************************/
2434 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2437 char adevice
[MAXDEVICENAME
];
2438 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2440 if (nt_devmode
== NULL
) {
2441 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2445 ZERO_STRUCTP(nt_devmode
);
2447 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2448 fstrcpy(nt_devmode
->devicename
, adevice
);
2450 fstrcpy(nt_devmode
->formname
, "Letter");
2452 nt_devmode
->specversion
= 0x0401;
2453 nt_devmode
->driverversion
= 0x0400;
2454 nt_devmode
->size
= 0x00DC;
2455 nt_devmode
->driverextra
= 0x0000;
2456 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2457 DEFAULTSOURCE
| COPIES
| SCALE
|
2458 PAPERSIZE
| ORIENTATION
;
2459 nt_devmode
->orientation
= 1;
2460 nt_devmode
->papersize
= PAPER_LETTER
;
2461 nt_devmode
->paperlength
= 0;
2462 nt_devmode
->paperwidth
= 0;
2463 nt_devmode
->scale
= 0x64;
2464 nt_devmode
->copies
= 1;
2465 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2466 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2467 nt_devmode
->color
= COLOR_MONOCHROME
;
2468 nt_devmode
->duplex
= DUP_SIMPLEX
;
2469 nt_devmode
->yresolution
= 0;
2470 nt_devmode
->ttoption
= TT_SUBDEV
;
2471 nt_devmode
->collate
= COLLATE_FALSE
;
2472 nt_devmode
->icmmethod
= 0;
2473 nt_devmode
->icmintent
= 0;
2474 nt_devmode
->mediatype
= 0;
2475 nt_devmode
->dithertype
= 0;
2477 /* non utilisés par un driver d'imprimante */
2478 nt_devmode
->logpixels
= 0;
2479 nt_devmode
->bitsperpel
= 0;
2480 nt_devmode
->pelswidth
= 0;
2481 nt_devmode
->pelsheight
= 0;
2482 nt_devmode
->displayflags
= 0;
2483 nt_devmode
->displayfrequency
= 0;
2484 nt_devmode
->reserved1
= 0;
2485 nt_devmode
->reserved2
= 0;
2486 nt_devmode
->panningwidth
= 0;
2487 nt_devmode
->panningheight
= 0;
2489 nt_devmode
->nt_dev_private
= NULL
;
2493 /****************************************************************************
2494 Deepcopy an NT devicemode.
2495 ****************************************************************************/
2497 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2499 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2501 if ( !nt_devicemode
)
2504 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2505 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2509 new_nt_devicemode
->nt_dev_private
= NULL
;
2510 if (nt_devicemode
->nt_dev_private
!= NULL
) {
2511 if ((new_nt_devicemode
->nt_dev_private
= memdup(nt_devicemode
->nt_dev_private
, nt_devicemode
->driverextra
)) == NULL
) {
2512 SAFE_FREE(new_nt_devicemode
);
2513 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2518 return new_nt_devicemode
;
2521 /****************************************************************************
2522 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2523 ****************************************************************************/
2525 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2527 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2529 if(nt_devmode
== NULL
)
2532 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2534 SAFE_FREE(nt_devmode
->nt_dev_private
);
2535 SAFE_FREE(*devmode_ptr
);
2538 /****************************************************************************
2539 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2540 ****************************************************************************/
2542 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2544 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2549 free_nt_devicemode(&info
->devmode
);
2551 TALLOC_FREE( *info_ptr
);
2555 /****************************************************************************
2556 ****************************************************************************/
2557 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2561 NT_DEVICEMODE devmode
;
2563 ZERO_STRUCT(devmode
);
2565 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2567 if (!*nt_devmode
) return len
;
2569 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2573 &devmode
.specversion
,
2574 &devmode
.driverversion
,
2576 &devmode
.driverextra
,
2577 &devmode
.orientation
,
2579 &devmode
.paperlength
,
2580 &devmode
.paperwidth
,
2583 &devmode
.defaultsource
,
2584 &devmode
.printquality
,
2587 &devmode
.yresolution
,
2593 &devmode
.bitsperpel
,
2595 &devmode
.pelsheight
,
2596 &devmode
.displayflags
,
2597 &devmode
.displayfrequency
,
2601 &devmode
.dithertype
,
2604 &devmode
.panningwidth
,
2605 &devmode
.panningheight
,
2606 &devmode
.nt_dev_private
);
2608 if (devmode
.nt_dev_private
) {
2609 /* the len in tdb_unpack is an int value and
2610 * devmode.driverextra is only a short
2612 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2613 devmode
.driverextra
=(uint16
)extra_len
;
2615 /* check to catch an invalid TDB entry so we don't segfault */
2616 if (devmode
.driverextra
== 0) {
2617 devmode
.nt_dev_private
= NULL
;
2621 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2623 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2624 if (devmode
.nt_dev_private
)
2625 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2630 /****************************************************************************
2631 Allocate and initialize a new slot.
2632 ***************************************************************************/
2634 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2639 if ( !name
|| !data
)
2642 /* allocate another slot in the NT_PRINTER_KEY array */
2644 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2645 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2651 key_index
= data
->num_keys
;
2653 /* initialze new key */
2655 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2657 if ( !(data
->keys
[key_index
].values
= TALLOC_ZERO_P( data
, REGVAL_CTR
)) )
2662 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2667 /****************************************************************************
2668 search for a registry key name in the existing printer data
2669 ***************************************************************************/
2671 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2675 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2676 if ( strequal( data
->keys
[i
].name
, name
) ) {
2678 /* cleanup memory */
2680 TALLOC_FREE( data
->keys
[i
].name
);
2681 TALLOC_FREE( data
->keys
[i
].values
);
2683 /* if not the end of the array, move remaining elements down one slot */
2686 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2687 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2694 return data
->num_keys
;
2697 /****************************************************************************
2698 search for a registry key name in the existing printer data
2699 ***************************************************************************/
2701 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2706 if ( !data
|| !name
)
2709 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2711 /* loop over all existing keys */
2713 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2714 if ( strequal(data
->keys
[i
].name
, name
) ) {
2715 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2725 /****************************************************************************
2726 ***************************************************************************/
2728 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2732 int num_subkeys
= 0;
2734 fstring
*subkeys_ptr
= NULL
;
2743 /* special case of asking for the top level printer data registry key names */
2745 if ( strlen(key
) == 0 ) {
2746 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2748 /* found a match, so allocate space and copy the name */
2750 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2751 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2756 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2763 /* asking for the subkeys of some key */
2764 /* subkey paths are stored in the key name using '\' as the delimiter */
2766 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2767 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2769 /* if we found the exact key, then break */
2770 key_len
= strlen( key
);
2771 if ( strlen(data
->keys
[i
].name
) == key_len
)
2774 /* get subkey path */
2776 p
= data
->keys
[i
].name
+ key_len
;
2779 fstrcpy( subkeyname
, p
);
2780 if ( (p
= strchr( subkeyname
, '\\' )) )
2783 /* don't add a key more than once */
2785 for ( j
=0; j
<num_subkeys
; j
++ ) {
2786 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2790 if ( j
!= num_subkeys
)
2793 /* found a match, so allocate space and copy the name */
2795 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2796 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2801 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2807 /* return error if the key was not found */
2809 if ( i
== data
->num_keys
) {
2810 SAFE_FREE(subkeys_ptr
);
2815 /* tag off the end */
2818 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2820 *subkeys
= subkeys_ptr
;
2826 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2829 smb_ucs2_t conv_str
[1024];
2832 regval_ctr_delvalue(ctr
, val_name
);
2833 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2834 STR_TERMINATE
| STR_NOALIGN
);
2835 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2836 (char *) conv_str
, str_size
);
2839 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2842 regval_ctr_delvalue(ctr
, val_name
);
2843 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2844 (char *) &dword
, sizeof(dword
));
2847 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2850 uint8 bin_bool
= (b
? 1 : 0);
2851 regval_ctr_delvalue(ctr
, val_name
);
2852 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2853 (char *) &bin_bool
, sizeof(bin_bool
));
2856 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2857 const char *multi_sz
)
2859 smb_ucs2_t
*conv_strs
= NULL
;
2862 /* a multi-sz has to have a null string terminator, i.e., the last
2863 string must be followed by two nulls */
2864 str_size
= strlen(multi_sz
) + 2;
2865 conv_strs
= SMB_CALLOC_ARRAY(smb_ucs2_t
, str_size
);
2870 /* Change to byte units. */
2871 str_size
*= sizeof(smb_ucs2_t
);
2872 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2873 STR_TERMINATE
| STR_NOALIGN
);
2875 regval_ctr_delvalue(ctr
, val_name
);
2876 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2877 (char *) conv_strs
, str_size
);
2878 safe_free(conv_strs
);
2882 /****************************************************************************
2883 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2885 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2886 * @return BOOL indicating success or failure
2887 ***************************************************************************/
2889 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2891 REGVAL_CTR
*ctr
= NULL
;
2894 char *allocated_string
= NULL
;
2895 const char *ascii_str
;
2898 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2899 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
2900 ctr
= info2
->data
->keys
[i
].values
;
2902 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2903 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2905 /* we make the assumption that the netbios name is the same
2906 as the DNS name sinc ethe former will be what we used to
2909 if ( get_mydnsdomname( dnssuffix
) )
2910 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2912 fstrcpy( longname
, global_myname() );
2914 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2916 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2917 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2918 SAFE_FREE(allocated_string
);
2920 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2921 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2922 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2923 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2924 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2925 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2926 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2927 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2928 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2930 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2931 (info2
->attributes
&
2932 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2934 switch (info2
->attributes
& 0x3) {
2936 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2939 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2942 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2945 ascii_str
= "unknown";
2947 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2952 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2956 REGVAL_CTR
*ctr
=NULL
;
2958 /* find the DsSpooler key */
2959 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2960 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
2961 ctr
= info2
->data
->keys
[i
].values
;
2963 regval_ctr_delvalue(ctr
, "objectGUID");
2964 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2965 (char *) &guid
, sizeof(struct uuid
));
2968 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2969 NT_PRINTER_INFO_LEVEL
*printer
)
2973 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2974 char *srv_dn_utf8
, **srv_cn_utf8
;
2977 const char *attrs
[] = {"objectGUID", NULL
};
2979 WERROR win_rc
= WERR_OK
;
2981 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
2983 /* figure out where to publish */
2984 ads_find_machine_acct(ads
, &res
, global_myname());
2986 /* We use ldap_get_dn here as we need the answer
2987 * in utf8 to call ldap_explode_dn(). JRA. */
2989 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2992 return WERR_SERVER_UNAVAILABLE
;
2994 ads_msgfree(ads
, res
);
2995 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
2997 ldap_memfree(srv_dn_utf8
);
2999 return WERR_SERVER_UNAVAILABLE
;
3001 /* Now convert to CH_UNIX. */
3002 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
3003 ldap_memfree(srv_dn_utf8
);
3004 ldap_memfree(srv_cn_utf8
);
3006 return WERR_SERVER_UNAVAILABLE
;
3008 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
3009 ldap_memfree(srv_dn_utf8
);
3010 ldap_memfree(srv_cn_utf8
);
3013 return WERR_SERVER_UNAVAILABLE
;
3016 ldap_memfree(srv_dn_utf8
);
3017 ldap_memfree(srv_cn_utf8
);
3019 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
3020 printer
->info_2
->sharename
, srv_dn
);
3023 SAFE_FREE(srv_cn_0
);
3025 /* build the ads mods */
3026 ctx
= talloc_init("nt_printer_publish_ads");
3027 mods
= ads_init_mods(ctx
);
3029 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3030 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3031 printer
->info_2
->sharename
);
3034 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3035 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
)
3036 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3038 if (!ADS_ERR_OK(ads_rc
))
3039 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3041 talloc_destroy(ctx
);
3043 /* retreive the guid and store it locally */
3044 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3046 ads_pull_guid(ads
, res
, &guid
);
3047 ads_msgfree(ads
, res
);
3048 store_printer_guid(printer
->info_2
, guid
);
3049 win_rc
= mod_a_printer(printer
, 2);
3056 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3057 NT_PRINTER_INFO_LEVEL
*printer
)
3061 char *prt_dn
= NULL
;
3063 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3065 /* remove the printer from the directory */
3066 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3067 printer
->info_2
->sharename
, global_myname());
3069 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
3070 prt_dn
= ads_get_dn(ads
, res
);
3071 ads_rc
= ads_del_dn(ads
, prt_dn
);
3072 ads_memfree(ads
, prt_dn
);
3075 ads_msgfree(ads
, res
);
3079 /****************************************************************************
3080 * Publish a printer in the directory
3082 * @param snum describing printer service
3083 * @return WERROR indicating status of publishing
3084 ***************************************************************************/
3086 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3089 ADS_STRUCT
*ads
= NULL
;
3090 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3093 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3094 if (!W_ERROR_IS_OK(win_rc
))
3098 case SPOOL_DS_PUBLISH
:
3099 case SPOOL_DS_UPDATE
:
3100 /* set the DsSpooler info and attributes */
3101 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3102 win_rc
= WERR_NOMEM
;
3106 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3108 case SPOOL_DS_UNPUBLISH
:
3109 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3112 win_rc
= WERR_NOT_SUPPORTED
;
3116 win_rc
= mod_a_printer(printer
, 2);
3117 if (!W_ERROR_IS_OK(win_rc
)) {
3118 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3122 ads
= ads_init(NULL
, NULL
, NULL
);
3124 DEBUG(3, ("ads_init() failed\n"));
3125 win_rc
= WERR_SERVER_UNAVAILABLE
;
3129 setenv(KRB5_ENV_CCNAME
, "KCM:SYSTEM", 1);
3131 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3133 SAFE_FREE(ads
->auth
.password
);
3134 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3137 /* ads_connect() will find the DC for us */
3138 ads_rc
= ads_connect(ads
);
3139 if (!ADS_ERR_OK(ads_rc
)) {
3140 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3141 win_rc
= WERR_ACCESS_DENIED
;
3146 case SPOOL_DS_PUBLISH
:
3147 case SPOOL_DS_UPDATE
:
3148 win_rc
= nt_printer_publish_ads(ads
, printer
);
3150 case SPOOL_DS_UNPUBLISH
:
3151 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3156 free_a_printer(&printer
, 2);
3161 WERROR
check_published_printers(void)
3164 ADS_STRUCT
*ads
= NULL
;
3166 int n_services
= lp_numservices();
3167 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3169 ads
= ads_init(NULL
, NULL
, NULL
);
3171 DEBUG(3, ("ads_init() failed\n"));
3172 return WERR_SERVER_UNAVAILABLE
;
3174 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3175 SAFE_FREE(ads
->auth
.password
);
3176 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3179 /* ads_connect() will find the DC for us */
3180 ads_rc
= ads_connect(ads
);
3181 if (!ADS_ERR_OK(ads_rc
)) {
3182 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3184 return WERR_ACCESS_DENIED
;
3187 for (snum
= 0; snum
< n_services
; snum
++) {
3188 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3191 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3192 lp_servicename(snum
))) &&
3193 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3194 nt_printer_publish_ads(ads
, printer
);
3196 free_a_printer(&printer
, 2);
3203 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3206 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3208 REGISTRY_VALUE
*guid_val
;
3212 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3214 if (!W_ERROR_IS_OK(win_rc
) ||
3215 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3216 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3217 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3218 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3220 free_a_printer(&printer
, 2);
3224 /* fetching printer guids really ought to be a separate function.. */
3225 if (guid
&& regval_size(guid_val
) == sizeof(struct uuid
))
3226 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
3228 free_a_printer(&printer
, 2);
3232 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3237 WERROR
check_published_printers(void)
3242 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3247 #endif /* HAVE_ADS */
3249 /****************************************************************************
3250 ***************************************************************************/
3252 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3254 NT_PRINTER_DATA
*data
;
3256 int removed_keys
= 0;
3260 empty_slot
= data
->num_keys
;
3263 return WERR_INVALID_PARAM
;
3265 /* remove all keys */
3267 if ( !strlen(key
) ) {
3269 TALLOC_FREE( data
);
3273 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3279 /* remove a specific key (and all subkeys) */
3281 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3282 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3283 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3284 data
->keys
[i
].name
));
3286 TALLOC_FREE( data
->keys
[i
].name
);
3287 TALLOC_FREE( data
->keys
[i
].values
);
3289 /* mark the slot as empty */
3291 ZERO_STRUCTP( &data
->keys
[i
] );
3295 /* find the first empty slot */
3297 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3298 if ( !data
->keys
[i
].name
) {
3305 if ( i
== data
->num_keys
)
3306 /* nothing was removed */
3307 return WERR_INVALID_PARAM
;
3309 /* move everything down */
3311 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3312 if ( data
->keys
[i
].name
) {
3313 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3314 ZERO_STRUCTP( &data
->keys
[i
] );
3322 data
->num_keys
-= removed_keys
;
3324 /* sanity check to see if anything is left */
3326 if ( !data
->num_keys
) {
3327 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3329 SAFE_FREE( data
->keys
);
3330 ZERO_STRUCTP( data
);
3336 /****************************************************************************
3337 ***************************************************************************/
3339 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3341 WERROR result
= WERR_OK
;
3344 /* we must have names on non-zero length */
3346 if ( !key
|| !*key
|| !value
|| !*value
)
3347 return WERR_INVALID_NAME
;
3349 /* find the printer key first */
3351 key_index
= lookup_printerkey( p2
->data
, key
);
3352 if ( key_index
== -1 )
3355 /* make sure the value exists so we can return the correct error code */
3357 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3358 return WERR_BADFILE
;
3360 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3362 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3368 /****************************************************************************
3369 ***************************************************************************/
3371 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3372 uint32 type
, uint8
*data
, int real_len
)
3374 WERROR result
= WERR_OK
;
3377 /* we must have names on non-zero length */
3379 if ( !key
|| !*key
|| !value
|| !*value
)
3380 return WERR_INVALID_NAME
;
3382 /* find the printer key first */
3384 key_index
= lookup_printerkey( p2
->data
, key
);
3385 if ( key_index
== -1 )
3386 key_index
= add_new_printer_key( p2
->data
, key
);
3388 if ( key_index
== -1 )
3391 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3392 type
, (const char *)data
, real_len
);
3394 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3395 key
, value
, type
, real_len
));
3400 /****************************************************************************
3401 ***************************************************************************/
3403 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3407 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3410 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3413 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3416 /****************************************************************************
3417 Unpack a list of registry values frem the TDB
3418 ***************************************************************************/
3420 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3424 pstring string
, valuename
, keyname
;
3428 REGISTRY_VALUE
*regval_p
;
3431 /* add the "PrinterDriverData" key first for performance reasons */
3433 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3435 /* loop and unpack the rest of the registry values */
3439 /* check to see if there are any more registry values */
3442 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3446 /* unpack the next regval */
3448 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3454 /* lookup for subkey names which have a type of REG_NONE */
3455 /* there's no data with this entry */
3457 if ( type
== REG_NONE
) {
3458 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3459 add_new_printer_key( printer_data
, string
);
3464 * break of the keyname from the value name.
3465 * Valuenames can have embedded '\'s so be careful.
3466 * only support one level of keys. See the
3467 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3471 str
= strchr_m( string
, '\\');
3473 /* Put in "PrinterDriverData" is no key specified */
3476 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3477 pstrcpy( valuename
, string
);
3481 pstrcpy( keyname
, string
);
3482 pstrcpy( valuename
, str
+1 );
3485 /* see if we need a new key */
3487 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3488 key_index
= add_new_printer_key( printer_data
, keyname
);
3490 if ( key_index
== -1 ) {
3491 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3496 /* add the new value */
3498 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3500 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3502 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3508 /****************************************************************************
3509 ***************************************************************************/
3511 static void map_to_os2_driver(fstring drivername
)
3513 static BOOL initialised
=False
;
3514 static fstring last_from
,last_to
;
3515 char *mapfile
= lp_os2_driver_map();
3516 char **lines
= NULL
;
3520 if (!strlen(drivername
))
3527 *last_from
= *last_to
= 0;
3531 if (strequal(drivername
,last_from
)) {
3532 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3533 fstrcpy(drivername
,last_to
);
3537 lines
= file_lines_load(mapfile
, &numlines
,0);
3538 if (numlines
== 0 || lines
== NULL
) {
3539 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3544 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3546 for( i
= 0; i
< numlines
; i
++) {
3547 char *nt_name
= lines
[i
];
3548 char *os2_name
= strchr(nt_name
,'=');
3555 while (isspace(*nt_name
))
3558 if (!*nt_name
|| strchr("#;",*nt_name
))
3562 int l
= strlen(nt_name
);
3563 while (l
&& isspace(nt_name
[l
-1])) {
3569 while (isspace(*os2_name
))
3573 int l
= strlen(os2_name
);
3574 while (l
&& isspace(os2_name
[l
-1])) {
3580 if (strequal(nt_name
,drivername
)) {
3581 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3582 fstrcpy(last_from
,drivername
);
3583 fstrcpy(last_to
,os2_name
);
3584 fstrcpy(drivername
,os2_name
);
3585 file_lines_free(lines
);
3590 file_lines_free(lines
);
3593 /****************************************************************************
3594 Get a default printer info 2 struct.
3595 ****************************************************************************/
3596 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char* sharename
)
3600 snum
= lp_servicenumber(sharename
);
3602 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3603 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
3604 servername
, sharename
);
3605 fstrcpy(info
->sharename
, sharename
);
3606 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
3608 /* by setting the driver name to an empty string, a local NT admin
3609 can now run the **local** APW to install a local printer driver
3610 for a Samba shared printer in 2.2. Without this, drivers **must** be
3611 installed on the Samba server for NT clients --jerry */
3612 #if 0 /* JERRY --do not uncomment-- */
3613 if (!*info
->drivername
)
3614 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3618 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
3620 pstrcpy(info
->comment
, "");
3621 fstrcpy(info
->printprocessor
, "winprint");
3622 fstrcpy(info
->datatype
, "RAW");
3624 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3626 info
->starttime
= 0; /* Minutes since 12:00am GMT */
3627 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
3629 info
->default_priority
= 1;
3630 info
->setuptime
= (uint32
)time(NULL
);
3633 * I changed this as I think it is better to have a generic
3634 * DEVMODE than to crash Win2k explorer.exe --jerry
3635 * See the HP Deskjet 990c Win2k drivers for an example.
3637 * However the default devmode appears to cause problems
3638 * with the HP CLJ 8500 PCL driver. Hence the addition of
3639 * the "default devmode" parameter --jerry 22/01/2002
3642 if (lp_default_devmode(snum
)) {
3643 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
)
3647 info
->devmode
= NULL
;
3650 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
))
3657 free_nt_devicemode(&info
->devmode
);
3659 return WERR_ACCESS_DENIED
;
3662 /****************************************************************************
3663 ****************************************************************************/
3664 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char *sharename
)
3667 int snum
= lp_servicenumber(sharename
);
3668 TDB_DATA kbuf
, dbuf
;
3669 fstring printername
;
3670 char adevice
[MAXDEVICENAME
];
3672 kbuf
= make_printer_tdbkey( sharename
);
3674 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3676 return get_a_printer_2_default(info
, servername
, sharename
);
3678 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3681 &info
->default_priority
,
3688 &info
->c_setprinter
,
3698 info
->printprocessor
,
3702 /* Samba has to have shared raw drivers. */
3703 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3704 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3706 /* Restore the stripped strings. */
3707 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3709 if ( lp_force_printername(snum
) )
3710 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3712 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
3714 fstrcpy(info
->printername
, printername
);
3716 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3719 * Some client drivers freak out if there is a NULL devmode
3720 * (probably the driver is not checking before accessing
3721 * the devmode pointer) --jerry
3723 * See comments in get_a_printer_2_default()
3726 if (lp_default_devmode(snum
) && !info
->devmode
) {
3727 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3729 info
->devmode
= construct_nt_devicemode(printername
);
3732 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
3733 if (info
->devmode
) {
3734 fstrcpy(info
->devmode
->devicename
, adevice
);
3737 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
3738 DEBUG(0,("unpack_values: talloc() failed!\n"));
3741 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3743 /* This will get the current RPC talloc context, but we should be
3744 passing this as a parameter... fixme... JRA ! */
3746 nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
);
3748 /* Fix for OS/2 drivers. */
3750 if (get_remote_arch() == RA_OS2
)
3751 map_to_os2_driver(info
->drivername
);
3753 SAFE_FREE(dbuf
.dptr
);
3755 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3756 sharename
, info
->printername
, info
->drivername
));
3761 /****************************************************************************
3762 Debugging function, dump at level 6 the struct in the logs.
3763 ****************************************************************************/
3764 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3767 NT_PRINTER_INFO_LEVEL_2
*info2
;
3769 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3774 if (printer
->info_2
== NULL
)
3778 info2
=printer
->info_2
;
3780 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3781 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3782 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3783 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3784 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3785 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3786 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3787 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3788 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3789 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3790 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3792 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3793 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3794 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3795 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3796 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3797 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3798 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3799 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3800 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3801 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3802 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3808 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3816 /****************************************************************************
3817 Update the changeid time.
3818 This is SO NASTY as some drivers need this to change, others need it
3819 static. This value will change every second, and I must hope that this
3820 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3822 ****************************************************************************/
3824 static uint32
rev_changeid(void)
3828 get_process_uptime(&tv
);
3831 /* Return changeid as msec since spooler restart */
3832 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3835 * This setting seems to work well but is too untested
3836 * to replace the above calculation. Left in for experiementation
3837 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3839 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3845 * The function below are the high level ones.
3846 * only those ones must be called from the spoolss code.
3850 /****************************************************************************
3851 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3852 ****************************************************************************/
3854 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3858 dump_a_printer(printer
, level
);
3864 * Update the changestamp. Emperical tests show that the
3865 * ChangeID is always updated,but c_setprinter is
3866 * global spooler variable (not per printer).
3869 /* ChangeID **must** be increasing over the lifetime
3870 of client's spoolss service in order for the
3871 client's cache to show updates */
3873 printer
->info_2
->changeid
= rev_changeid();
3876 * Because one day someone will ask:
3877 * NT->NT An admin connection to a remote
3878 * printer show changes imeediately in
3879 * the properities dialog
3881 * A non-admin connection will only show the
3882 * changes after viewing the properites page
3883 * 2 times. Seems to be related to a
3884 * race condition in the client between the spooler
3885 * updating the local cache and the Explorer.exe GUI
3886 * actually displaying the properties.
3888 * This is fixed in Win2k. admin/non-admin
3889 * connections both display changes immediately.
3894 result
=update_a_printer_2(printer
->info_2
);
3899 result
=WERR_UNKNOWN_LEVEL
;
3906 /****************************************************************************
3907 Initialize printer devmode & data with previously saved driver init values.
3908 ****************************************************************************/
3910 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3914 TDB_DATA kbuf
, dbuf
;
3915 NT_PRINTER_INFO_LEVEL_2 info
;
3921 * Delete any printer data 'values' already set. When called for driver
3922 * replace, there will generally be some, but during an add printer, there
3923 * should not be any (if there are delete them).
3926 if ( info_ptr
->data
)
3927 delete_all_printer_data( info_ptr
, "" );
3929 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3932 kbuf
.dsize
= strlen(key
)+1;
3934 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3937 * When changing to a driver that has no init info in the tdb, remove
3938 * the previous drivers init info and leave the new on blank.
3940 free_nt_devicemode(&info_ptr
->devmode
);
3945 * Get the saved DEVMODE..
3948 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3951 * The saved DEVMODE contains the devicename from the printer used during
3952 * the initialization save. Change it to reflect the new printer.
3955 if ( info
.devmode
) {
3956 ZERO_STRUCT(info
.devmode
->devicename
);
3957 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3961 * NT/2k does not change out the entire DeviceMode of a printer
3962 * when changing the driver. Only the driverextra, private, &
3963 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3965 * Later examination revealed that Windows NT/2k does reset the
3966 * the printer's device mode, bit **only** when you change a
3967 * property of the device mode such as the page orientation.
3972 /* Bind the saved DEVMODE to the new the printer */
3974 free_nt_devicemode(&info_ptr
->devmode
);
3975 info_ptr
->devmode
= info
.devmode
;
3977 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3978 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3980 /* Add the printer data 'values' to the new printer */
3982 if ( !(info_ptr
->data
= TALLOC_ZERO_P( info_ptr
, NT_PRINTER_DATA
)) ) {
3983 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3987 len
+= unpack_values( info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3990 SAFE_FREE(dbuf
.dptr
);
3995 /****************************************************************************
3996 Initialize printer devmode & data with previously saved driver init values.
3997 When a printer is created using AddPrinter, the drivername bound to the
3998 printer is used to lookup previously saved driver initialization info, which
3999 is bound to the new printer.
4000 ****************************************************************************/
4002 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4004 BOOL result
= False
;
4008 result
= set_driver_init_2(printer
->info_2
);
4012 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4020 /****************************************************************************
4021 Delete driver init data stored for a specified driver
4022 ****************************************************************************/
4024 BOOL
del_driver_init(char *drivername
)
4029 if (!drivername
|| !*drivername
) {
4030 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4034 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
4037 kbuf
.dsize
= strlen(key
)+1;
4039 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
4041 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
4044 /****************************************************************************
4045 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4046 in the tdb. Note: this is different from the driver entry and the printer
4047 entry. There should be a single driver init entry for each driver regardless
4048 of whether it was installed from NT or 2K. Technically, they should be
4049 different, but they work out to the same struct.
4050 ****************************************************************************/
4052 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4056 int buflen
, len
, ret
;
4057 TDB_DATA kbuf
, dbuf
;
4064 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4066 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
4069 buf
= (char *)SMB_REALLOC(buf
, len
);
4071 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4079 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
4082 kbuf
.dsize
= strlen(key
)+1;
4086 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
4090 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4094 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4095 info
->sharename
, info
->drivername
));
4100 /****************************************************************************
4101 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4102 ****************************************************************************/
4104 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4108 dump_a_printer(printer
, level
);
4112 result
= update_driver_init_2(printer
->info_2
);
4122 /****************************************************************************
4123 Convert the printer data value, a REG_BINARY array, into an initialization
4124 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4125 got to keep the endians happy :).
4126 ****************************************************************************/
4128 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
4130 BOOL result
= False
;
4134 ZERO_STRUCT(devmode
);
4136 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
4137 ps
.data_p
= (char *)data
;
4138 ps
.buffer_size
= data_len
;
4140 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
4141 result
= convert_devicemode("", &devmode
, &nt_devmode
);
4143 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4148 /****************************************************************************
4149 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4151 1. Use the driver's config DLL to this UNC printername and:
4152 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4153 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4154 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4156 The last step triggers saving the "driver initialization" information for
4157 this printer into the tdb. Later, new printers that use this driver will
4158 have this initialization information bound to them. This simulates the
4159 driver initialization, as if it had run on the Samba server (as it would
4162 The Win32 client side code requirement sucks! But until we can run arbitrary
4163 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4165 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4166 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4167 about it and you will realize why. JRR 010720
4168 ****************************************************************************/
4170 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4172 WERROR status
= WERR_OK
;
4173 TALLOC_CTX
*ctx
= NULL
;
4174 NT_DEVICEMODE
*nt_devmode
= NULL
;
4175 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4178 * When the DEVMODE is already set on the printer, don't try to unpack it.
4180 DEBUG(8,("save_driver_init_2: Enter...\n"));
4182 if ( !printer
->info_2
->devmode
&& data_len
) {
4184 * Set devmode on printer info, so entire printer initialization can be
4188 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4191 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4192 status
= WERR_NOMEM
;
4196 ZERO_STRUCTP(nt_devmode
);
4199 * The DEVMODE is held in the 'data' component of the param in raw binary.
4200 * Convert it to to a devmode structure
4202 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4203 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4204 status
= WERR_INVALID_PARAM
;
4208 printer
->info_2
->devmode
= nt_devmode
;
4212 * Pack up and add (or update) the DEVMODE and any current printer data to
4213 * a 'driver init' element in the tdb
4217 if ( update_driver_init(printer
, 2) != 0 ) {
4218 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4219 status
= WERR_NOMEM
;
4224 * If driver initialization info was successfully saved, set the current
4225 * printer to match it. This allows initialization of the current printer
4226 * as well as the driver.
4228 status
= mod_a_printer(printer
, 2);
4229 if (!W_ERROR_IS_OK(status
)) {
4230 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4231 printer
->info_2
->printername
));
4235 talloc_destroy(ctx
);
4236 free_nt_devicemode( &nt_devmode
);
4238 printer
->info_2
->devmode
= tmp_devmode
;
4243 /****************************************************************************
4244 Update the driver init info (DEVMODE and specifics) for a printer
4245 ****************************************************************************/
4247 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4249 WERROR status
= WERR_OK
;
4253 status
= save_driver_init_2( printer
, data
, data_len
);
4256 status
= WERR_UNKNOWN_LEVEL
;
4263 /****************************************************************************
4264 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4266 Previously the code had a memory allocation problem because it always
4267 used the TALLOC_CTX from the Printer_entry*. This context lasts
4268 as a long as the original handle is open. So if the client made a lot
4269 of getprinter[data]() calls, the memory usage would climb. Now we use
4270 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4271 still use the Printer_entry->ctx for maintaining the cache copy though
4272 since that object must live as long as the handle by definition.
4275 ****************************************************************************/
4277 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4278 const char *sharename
)
4283 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4285 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4286 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4292 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4293 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4294 TALLOC_FREE( *pp_printer
);
4299 fstrcpy( servername
, print_hnd
->servername
);
4301 fstrcpy( servername
, "%L" );
4302 standard_sub_basic( "", servername
, sizeof(servername
)-1 );
4305 result
= get_a_printer_2( (*pp_printer
)->info_2
, servername
, sharename
);
4308 /* we have a new printer now. Save it with this handle */
4310 if ( !W_ERROR_IS_OK(result
) ) {
4311 TALLOC_FREE( *pp_printer
);
4312 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4313 sharename
, (unsigned int)level
, dos_errstr(result
)));
4317 dump_a_printer( *pp_printer
, level
);
4322 TALLOC_FREE( *pp_printer
);
4323 return WERR_UNKNOWN_LEVEL
;
4329 /****************************************************************************
4330 Deletes a NT_PRINTER_INFO_LEVEL struct.
4331 ****************************************************************************/
4333 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4335 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4342 if ( printer
->info_2
)
4343 free_nt_printer_info_level_2(&printer
->info_2
);
4347 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4351 TALLOC_FREE(*pp_printer
);
4356 /****************************************************************************
4357 ****************************************************************************/
4358 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4361 DEBUG(104,("adding a printer at level [%d]\n", level
));
4362 dump_a_printer_driver(driver
, level
);
4366 result
=add_a_printer_driver_3(driver
.info_3
);
4370 result
=add_a_printer_driver_6(driver
.info_6
);
4380 /****************************************************************************
4381 ****************************************************************************/
4383 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4384 fstring drivername
, const char *architecture
, uint32 version
)
4390 /* Sometime we just want any version of the driver */
4392 if ( version
== DRIVER_ANY_VERSION
) {
4393 /* look for Win2k first and then for NT4 */
4394 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4397 if ( !W_ERROR_IS_OK(result
) ) {
4398 result
= get_a_printer_driver_3( &driver
->info_3
,
4399 drivername
, architecture
, 2 );
4402 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4403 architecture
, version
);
4412 if (W_ERROR_IS_OK(result
))
4413 dump_a_printer_driver(*driver
, level
);
4418 /****************************************************************************
4419 ****************************************************************************/
4420 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4427 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4428 if (driver
.info_3
!= NULL
)
4430 info3
=driver
.info_3
;
4431 SAFE_FREE(info3
->dependentfiles
);
4432 ZERO_STRUCTP(info3
);
4442 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4443 if (driver
.info_6
!= NULL
) {
4444 info6
=driver
.info_6
;
4445 SAFE_FREE(info6
->dependentfiles
);
4446 SAFE_FREE(info6
->previousnames
);
4447 ZERO_STRUCTP(info6
);
4463 /****************************************************************************
4464 Determine whether or not a particular driver is currently assigned
4466 ****************************************************************************/
4468 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4471 int n_services
= lp_numservices();
4472 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4473 BOOL in_use
= False
;
4478 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4480 /* loop through the printers.tdb and check for the drivername */
4482 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4483 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4486 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4489 if ( strequal(info_3
->name
, printer
->info_2
->drivername
) )
4492 free_a_printer( &printer
, 2 );
4495 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4498 NT_PRINTER_DRIVER_INFO_LEVEL d
;
4501 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3
->name
));
4503 /* we can still remove the driver if there is one of
4504 "Windows NT x86" version 2 or 3 left */
4506 if ( !strequal( "Windows NT x86", info_3
->environment
) ) {
4507 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4510 switch ( info_3
->cversion
) {
4512 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 3 );
4515 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 2 );
4518 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4520 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4525 /* now check the error code */
4527 if ( W_ERROR_IS_OK(werr
) ) {
4528 /* it's ok to remove the driver, we have other architctures left */
4530 free_a_printer_driver( d
, 3 );
4534 /* report that the driver is not in use by default */
4540 /**********************************************************************
4541 Check to see if a ogiven file is in use by *info
4542 *********************************************************************/
4544 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4551 if ( strequal(file
, info
->driverpath
) )
4554 if ( strequal(file
, info
->datafile
) )
4557 if ( strequal(file
, info
->configfile
) )
4560 if ( strequal(file
, info
->helpfile
) )
4563 /* see of there are any dependent files to examine */
4565 if ( !info
->dependentfiles
)
4568 while ( *info
->dependentfiles
[i
] ) {
4569 if ( strequal(file
, info
->dependentfiles
[i
]) )
4578 /**********************************************************************
4579 Utility function to remove the dependent file pointed to by the
4580 input parameter from the list
4581 *********************************************************************/
4583 static void trim_dependent_file( fstring files
[], int idx
)
4586 /* bump everything down a slot */
4588 while( *files
[idx
+1] ) {
4589 fstrcpy( files
[idx
], files
[idx
+1] );
4598 /**********************************************************************
4599 Check if any of the files used by src are also used by drv
4600 *********************************************************************/
4602 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4603 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4605 BOOL in_use
= False
;
4611 /* check each file. Remove it from the src structure if it overlaps */
4613 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4615 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4616 fstrcpy( src
->driverpath
, "" );
4619 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4621 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4622 fstrcpy( src
->datafile
, "" );
4625 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4627 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4628 fstrcpy( src
->configfile
, "" );
4631 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4633 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4634 fstrcpy( src
->helpfile
, "" );
4637 /* are there any dependentfiles to examine? */
4639 if ( !src
->dependentfiles
)
4642 while ( *src
->dependentfiles
[i
] ) {
4643 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4645 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4646 trim_dependent_file( src
->dependentfiles
, i
);
4654 /****************************************************************************
4655 Determine whether or not a particular driver files are currently being
4656 used by any other driver.
4658 Return value is True if any files were in use by other drivers
4659 and False otherwise.
4661 Upon return, *info has been modified to only contain the driver files
4662 which are not in use
4663 ****************************************************************************/
4665 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4670 fstring
*list
= NULL
;
4671 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4676 version
= info
->cversion
;
4678 /* loop over all driver versions */
4680 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4682 /* get the list of drivers */
4685 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4687 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4688 ndrivers
, info
->environment
, version
));
4690 /* check each driver for overlap in files */
4692 for (i
=0; i
<ndrivers
; i
++) {
4693 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4695 ZERO_STRUCT(driver
);
4697 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4702 /* check if d2 uses any files from d1 */
4703 /* only if this is a different driver than the one being deleted */
4705 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4706 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4707 free_a_printer_driver(driver
, 3);
4713 free_a_printer_driver(driver
, 3);
4718 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4720 driver
.info_3
= info
;
4722 if ( DEBUGLEVEL
>= 20 )
4723 dump_a_printer_driver( driver
, 3 );
4728 /****************************************************************************
4729 Actually delete the driver files. Make sure that
4730 printer_driver_files_in_use() return False before calling
4732 ****************************************************************************/
4734 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4739 connection_struct
*conn
;
4749 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4752 * Connect to the print$ share under the same account as the
4753 * user connected to the rpc pipe. Note we must be root to
4757 null_pw
= data_blob( NULL
, 0 );
4758 fstrcpy(res_type
, "A:");
4760 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4764 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4768 if ( !CAN_WRITE(conn
) ) {
4769 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4773 /* Save who we are - we are temporarily becoming the connection user. */
4775 if ( !become_user(conn
, conn
->vuid
) ) {
4776 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4780 /* now delete the files; must strip the '\print$' string from
4783 if ( *info_3
->driverpath
) {
4784 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4786 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4787 DEBUG(10,("deleting driverfile [%s]\n", s
));
4788 unlink_internals(conn
, 0, file
, False
);
4792 if ( *info_3
->configfile
) {
4793 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4795 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4796 DEBUG(10,("deleting configfile [%s]\n", s
));
4797 unlink_internals(conn
, 0, file
, False
);
4801 if ( *info_3
->datafile
) {
4802 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4804 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4805 DEBUG(10,("deleting datafile [%s]\n", s
));
4806 unlink_internals(conn
, 0, file
, False
);
4810 if ( *info_3
->helpfile
) {
4811 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4813 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4814 DEBUG(10,("deleting helpfile [%s]\n", s
));
4815 unlink_internals(conn
, 0, file
, False
);
4819 /* check if we are done removing files */
4821 if ( info_3
->dependentfiles
) {
4822 while ( info_3
->dependentfiles
[i
][0] ) {
4825 /* bypass the "\print$" portion of the path */
4827 if ( (p
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4829 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4830 DEBUG(10,("deleting dependent file [%s]\n", file
));
4831 unlink_internals(conn
, 0, file
, False
);
4843 /****************************************************************************
4844 Remove a printer driver from the TDB. This assumes that the the driver was
4845 previously looked up.
4846 ***************************************************************************/
4848 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4849 uint32 version
, BOOL delete_files
)
4853 TDB_DATA kbuf
, dbuf
;
4854 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4856 /* delete the tdb data first */
4858 arch
= get_short_archi(info_3
->environment
);
4859 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4860 arch
, version
, info_3
->name
);
4862 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4863 key
, delete_files
? "TRUE" : "FALSE" ));
4865 ctr
.info_3
= info_3
;
4866 dump_a_printer_driver( ctr
, 3 );
4869 kbuf
.dsize
=strlen(key
)+1;
4871 /* check if the driver actually exists for this environment */
4873 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4875 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4876 return WERR_UNKNOWN_PRINTER_DRIVER
;
4879 SAFE_FREE( dbuf
.dptr
);
4881 /* ok... the driver exists so the delete should return success */
4883 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4884 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4885 return WERR_ACCESS_DENIED
;
4889 * now delete any associated files if delete_files == True
4890 * even if this part failes, we return succes because the
4891 * driver doesn not exist any more
4895 delete_driver_files( info_3
, user
);
4898 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4903 /****************************************************************************
4904 Store a security desc for a printer.
4905 ****************************************************************************/
4907 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
4909 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4910 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4912 TALLOC_CTX
*mem_ctx
= NULL
;
4916 mem_ctx
= talloc_init("nt_printing_setsec");
4917 if (mem_ctx
== NULL
)
4920 /* The old owner and group sids of the security descriptor are not
4921 present when new ACEs are added or removed by changing printer
4922 permissions through NT. If they are NULL in the new security
4923 descriptor then copy them over from the old one. */
4925 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4926 DOM_SID
*owner_sid
, *group_sid
;
4927 SEC_ACL
*dacl
, *sacl
;
4928 SEC_DESC
*psd
= NULL
;
4931 nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
);
4933 /* Pick out correct owner and group sids */
4935 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4936 secdesc_ctr
->sec
->owner_sid
:
4937 old_secdesc_ctr
->sec
->owner_sid
;
4939 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4940 secdesc_ctr
->sec
->grp_sid
:
4941 old_secdesc_ctr
->sec
->grp_sid
;
4943 dacl
= secdesc_ctr
->sec
->dacl
?
4944 secdesc_ctr
->sec
->dacl
:
4945 old_secdesc_ctr
->sec
->dacl
;
4947 sacl
= secdesc_ctr
->sec
->sacl
?
4948 secdesc_ctr
->sec
->sacl
:
4949 old_secdesc_ctr
->sec
->sacl
;
4951 /* Make a deep copy of the security descriptor */
4953 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4954 owner_sid
, group_sid
,
4959 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4962 if (!new_secdesc_ctr
) {
4963 new_secdesc_ctr
= secdesc_ctr
;
4966 /* Store the security descriptor in a tdb */
4968 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4969 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4971 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4973 status
= WERR_BADFUNC
;
4977 key
= make_printers_secdesc_tdbkey( sharename
);
4979 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4982 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
4983 status
= WERR_BADFUNC
;
4986 /* Free malloc'ed memory */
4992 talloc_destroy(mem_ctx
);
4996 /****************************************************************************
4997 Construct a default security descriptor buffer for a printer.
4998 ****************************************************************************/
5000 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5002 SEC_ACE ace
[5]; /* max number of ace entries */
5005 SEC_ACL
*psa
= NULL
;
5006 SEC_DESC_BUF
*sdb
= NULL
;
5007 SEC_DESC
*psd
= NULL
;
5011 /* Create an ACE where Everyone is allowed to print */
5013 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
5014 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5015 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5017 /* Add the domain admins group if we are a DC */
5020 DOM_SID domadmins_sid
;
5022 sid_copy(&domadmins_sid
, get_global_sam_sid());
5023 sid_append_rid(&domadmins_sid
, DOMAIN_GROUP_RID_ADMINS
);
5025 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5026 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5027 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5028 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5029 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5030 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5032 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5033 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5035 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5036 init_sec_ace(&ace
[i
++], &adm_sid
,
5037 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5038 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5039 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5040 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5043 /* add BUILTIN\Administrators as FULL CONTROL */
5045 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5046 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5047 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5048 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5049 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5050 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5051 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5053 /* Make the security descriptor owned by the BUILTIN\Administrators */
5055 /* The ACL revision number in rpc_secdesc.h differs from the one
5056 created by NT when setting ACE entries in printer
5057 descriptors. NT4 complains about the property being edited by a
5060 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5061 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5062 &global_sid_Builtin_Administrators
,
5063 &global_sid_Builtin_Administrators
,
5064 NULL
, psa
, &sd_size
);
5068 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5072 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5074 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5075 (unsigned int)sd_size
));
5080 /****************************************************************************
5081 Get a security desc for a printer.
5082 ****************************************************************************/
5084 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5090 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5091 sharename
= temp
+ 1;
5094 /* Fetch security descriptor from tdb */
5096 key
= make_printers_secdesc_tdbkey( sharename
);
5098 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
5099 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5101 DEBUG(4,("using default secdesc for %s\n", sharename
));
5103 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
5107 /* Save default security descriptor for later */
5109 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
5110 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
5112 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
5113 tdb_prs_store(tdb_printers
, key
, &ps
);
5120 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5121 this security descriptor has been created when winbindd was
5122 down. Take ownership of security descriptor. */
5124 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
5127 /* Change sd owner to workgroup administrator */
5129 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5130 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5131 SEC_DESC
*psd
= NULL
;
5136 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5138 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
5140 (*secdesc_ctr
)->sec
->grp_sid
,
5141 (*secdesc_ctr
)->sec
->sacl
,
5142 (*secdesc_ctr
)->sec
->dacl
,
5145 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5147 /* Swap with other one */
5149 *secdesc_ctr
= new_secdesc_ctr
;
5153 nt_printing_setsec(sharename
, *secdesc_ctr
);
5157 if (DEBUGLEVEL
>= 10) {
5158 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
5161 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5162 sharename
, the_acl
->num_aces
));
5164 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5167 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5169 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
5170 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
5171 the_acl
->ace
[i
].info
.mask
));
5181 1: level not implemented
5182 2: file doesn't exist
5183 3: can't allocate memory
5184 4: can't free memory
5185 5: non existant struct
5189 A printer and a printer driver are 2 different things.
5190 NT manages them separatelly, Samba does the same.
5191 Why ? Simply because it's easier and it makes sense !
5193 Now explanation: You have 3 printers behind your samba server,
5194 2 of them are the same make and model (laser A and B). But laser B
5195 has an 3000 sheet feeder and laser A doesn't such an option.
5196 Your third printer is an old dot-matrix model for the accounting :-).
5198 If the /usr/local/samba/lib directory (default dir), you will have
5199 5 files to describe all of this.
5201 3 files for the printers (1 by printer):
5204 NTprinter_accounting
5205 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5206 NTdriver_printer model X
5207 NTdriver_printer model Y
5209 jfm: I should use this comment for the text file to explain
5210 same thing for the forms BTW.
5211 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5215 /* Convert generic access rights to printer object specific access rights.
5216 It turns out that NT4 security descriptors use generic access rights and
5217 NT5 the object specific ones. */
5219 void map_printer_permissions(SEC_DESC
*sd
)
5223 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5224 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
5225 &printer_generic_mapping
);
5229 /****************************************************************************
5230 Check a user has permissions to perform the given operation. We use the
5231 permission constants defined in include/rpc_spoolss.h to check the various
5232 actions we perform when checking printer access.
5234 PRINTER_ACCESS_ADMINISTER:
5235 print_queue_pause, print_queue_resume, update_printer_sec,
5236 update_printer, spoolss_addprinterex_level_2,
5237 _spoolss_setprinterdata
5242 JOB_ACCESS_ADMINISTER:
5243 print_job_delete, print_job_pause, print_job_resume,
5246 Try access control in the following order (for performance reasons):
5247 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5248 2) check security descriptor (bit comparisons in memory)
5249 3) "printer admins" (may result in numerous calls to winbind)
5251 ****************************************************************************/
5252 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5254 SEC_DESC_BUF
*secdesc
= NULL
;
5255 uint32 access_granted
;
5259 TALLOC_CTX
*mem_ctx
= NULL
;
5260 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5262 /* If user is NULL then use the current_user structure */
5265 user
= ¤t_user
;
5267 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5269 if ( user
->ut
.uid
== 0 || user_has_privileges(user
->nt_user_token
, &se_printop
) ) {
5273 /* Get printer name */
5275 pname
= PRINTERNAME(snum
);
5277 if (!pname
|| !*pname
) {
5282 /* Get printer security descriptor */
5284 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5289 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
5291 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5292 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5294 /* Create a child security descriptor to check permissions
5295 against. This is because print jobs are child objects
5296 objects of a printer. */
5298 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
5300 /* Now this is the bit that really confuses me. The access
5301 type needs to be changed from JOB_ACCESS_ADMINISTER to
5302 PRINTER_ACCESS_ADMINISTER for this to work. Something
5303 to do with the child (job) object becoming like a
5306 access_type
= PRINTER_ACCESS_ADMINISTER
;
5311 map_printer_permissions(secdesc
->sec
);
5313 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
5314 &access_granted
, &status
);
5316 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5318 /* see if we need to try the printer admin list */
5320 if ((access_granted
== 0) &&
5321 (token_contains_name_in_list(uidtoname(user
->ut
.uid
), NULL
,
5322 user
->nt_user_token
,
5323 lp_printer_admin(snum
)))) {
5327 talloc_destroy(mem_ctx
);
5335 /****************************************************************************
5336 Check the time parameters allow a print operation.
5337 *****************************************************************************/
5339 BOOL
print_time_access_check(int snum
)
5341 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5343 time_t now
= time(NULL
);
5347 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5350 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5354 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5356 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5359 free_a_printer(&printer
, 2);
5367 /****************************************************************************
5368 Fill in the servername sent in the _spoolss_open_printer_ex() call
5369 ****************************************************************************/
5371 char* get_server_name( Printer_entry
*printer
)
5373 return printer
->servername
;