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) {
353 if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 ) {
357 /* upgrade the security descriptor */
361 prs_init( &ps
, 0, ctx
, UNMARSHALL
);
362 prs_give_memory( &ps
, data
.dptr
, data
.dsize
, False
);
364 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig
, &ps
, 1 ) ) {
365 /* delete bad entries */
366 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key
.dptr
));
367 tdb_delete( tdb_printers
, key
);
378 /* is this even valid? */
385 /* update access masks */
387 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
388 switch ( sec
->dacl
->aces
[i
].access_mask
) {
389 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
390 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_PRINT
;
393 case GENERIC_ALL_ACCESS
:
394 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_FULL_CONTROL
;
397 case READ_CONTROL_ACCESS
:
398 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
400 default: /* no change */
405 /* create a new SEC_DESC with the appropriate owner and group SIDs */
407 string_to_sid(&sid
, "S-1-5-32-544" );
408 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
410 NULL
, NULL
, &size_new_sec
);
415 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
421 if ( !(sd_store
= sec_desc_merge( ctx
, sd_new
, sd_orig
)) ) {
422 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
431 sd_size
= sec_desc_size(sd_store
->sd
) + sizeof(SEC_DESC_BUF
);
432 prs_init(&ps
, sd_size
, ctx
, MARSHALL
);
434 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store
, &ps
, 1 ) ) {
435 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
440 data
.dptr
= prs_data_p( &ps
);
441 data
.dsize
= sd_size
;
443 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
447 /* 0 to continue and non-zero to stop traversal */
449 return (result
== -1);
452 /*******************************************************************
453 *******************************************************************/
455 static BOOL
upgrade_to_version_4(void)
460 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
462 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
465 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
467 talloc_destroy( ctx
);
469 return ( result
!= -1 );
472 /*******************************************************************
473 Fix an issue with security descriptors. Printer sec_desc must
474 use more than the generic bits that were previously used
475 in <= 3.0.14a. They must also have a owner and group SID assigned.
476 Otherwise, any printers than have been migrated to a Windows
477 host using printmig.exe will not be accessible.
478 *******************************************************************/
480 static int normalize_printers_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
481 TDB_DATA data
, void *state
)
485 if (!data
.dptr
|| data
.dsize
== 0)
488 /* upgrade printer records and security descriptors */
490 if ( strncmp( key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
491 new_key
= make_printer_tdbkey( key
.dptr
+strlen(PRINTERS_PREFIX
) );
493 else if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
494 new_key
.dptr
= make_printers_secdesc_tdbkey( key
.dptr
+strlen(SECDESC_PREFIX
) );
495 new_key
.dsize
= strlen( new_key
.dptr
) + 1;
498 /* ignore this record */
502 /* delete the original record and store under the normalized key */
504 if ( tdb_delete( the_tdb
, key
) != 0 ) {
505 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
510 if ( tdb_store( the_tdb
, new_key
, data
, TDB_REPLACE
) != 0 ) {
511 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
519 /*******************************************************************
520 *******************************************************************/
522 static BOOL
upgrade_to_version_5(void)
527 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
529 if ( !(ctx
= talloc_init( "upgrade_to_version_5" )) )
532 result
= tdb_traverse( tdb_printers
, normalize_printers_fn
, NULL
);
534 talloc_destroy( ctx
);
536 return ( result
!= -1 );
539 /****************************************************************************
540 Open the NT printing tdbs. Done once before fork().
541 ****************************************************************************/
543 BOOL
nt_printing_init(void)
545 const char *vstring
= "INFO/version";
549 if ( tdb_drivers
&& tdb_printers
&& tdb_forms
)
553 tdb_close(tdb_drivers
);
554 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
556 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
557 lock_path("ntdrivers.tdb"), strerror(errno
) ));
562 tdb_close(tdb_printers
);
563 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
565 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
566 lock_path("ntprinters.tdb"), strerror(errno
) ));
571 tdb_close(tdb_forms
);
572 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
574 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
575 lock_path("ntforms.tdb"), strerror(errno
) ));
579 /* handle a Samba upgrade */
581 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
583 DEBUG(10, ("Fresh database\n"));
584 tdb_store_int32( tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
585 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
588 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
590 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
591 if (!upgrade_to_version_3())
593 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
594 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
597 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
598 /* Written on a bigendian machine with old fetch_int code. Save as le. */
599 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
600 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
601 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
604 if (vers_id
== NTDRIVERS_DATABASE_VERSION_3
) {
605 if ( !upgrade_to_version_4() )
607 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_4
);
608 vers_id
= NTDRIVERS_DATABASE_VERSION_4
;
611 if (vers_id
== NTDRIVERS_DATABASE_VERSION_4
) {
612 if ( !upgrade_to_version_5() )
614 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
615 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
619 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
620 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id
));
625 update_c_setprinter(True
);
628 * register callback to handle updating printers as new
629 * drivers are installed
632 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
635 * register callback to handle updating printer data
636 * when a driver is initialized
639 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
641 /* of course, none of the message callbacks matter if you don't
642 tell messages.c that you interested in receiving PRINT_GENERAL
643 msgs. This is done in claim_connection() */
646 if ( lp_security() == SEC_ADS
) {
647 win_rc
= check_published_printers();
648 if (!W_ERROR_IS_OK(win_rc
))
649 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
655 /*******************************************************************
656 Function to allow filename parsing "the old way".
657 ********************************************************************/
659 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
660 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
663 unix_clean_name(name
);
664 trim_string(name
,"/","/");
665 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
668 /*******************************************************************
669 tdb traversal function for counting printers.
670 ********************************************************************/
672 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
673 TDB_DATA data
, void *context
)
675 int *printer_count
= (int*)context
;
677 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
679 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
685 /*******************************************************************
686 Update the spooler global c_setprinter. This variable is initialized
687 when the parent smbd starts with the number of existing printers. It
688 is monotonically increased by the current number of printers *after*
689 each add or delete printer RPC. Only Microsoft knows why... JRR020119
690 ********************************************************************/
692 uint32
update_c_setprinter(BOOL initialize
)
695 int32 printer_count
= 0;
697 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
699 /* Traverse the tdb, counting the printers */
700 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
702 /* If initializing, set c_setprinter to current printers count
703 * otherwise, bump it by the current printer count
706 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
708 c_setprinter
= printer_count
;
710 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
711 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
713 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
715 return (uint32
)c_setprinter
;
718 /*******************************************************************
719 Get the spooler global c_setprinter, accounting for initialization.
720 ********************************************************************/
722 uint32
get_c_setprinter(void)
724 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
726 if (c_setprinter
== (int32
)-1)
727 c_setprinter
= update_c_setprinter(True
);
729 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
731 return (uint32
)c_setprinter
;
734 /****************************************************************************
735 Get builtin form struct list.
736 ****************************************************************************/
738 int get_builtin_ntforms(nt_forms_struct
**list
)
740 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
744 return sizeof(default_forms
) / sizeof(default_forms
[0]);
747 /****************************************************************************
748 get a builtin form struct
749 ****************************************************************************/
751 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
755 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
756 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
757 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
758 for (i
=0;i
<count
;i
++) {
759 if (strequal(form_name
,default_forms
[i
].name
)) {
760 DEBUGADD(6,("Found builtin form %s \n", form_name
));
761 memcpy(form
,&default_forms
[i
],sizeof(*form
));
769 /****************************************************************************
770 get a form struct list.
771 ****************************************************************************/
773 int get_ntforms(nt_forms_struct
**list
)
775 TDB_DATA kbuf
, newkey
, dbuf
;
776 nt_forms_struct form
;
783 for (kbuf
= tdb_firstkey(tdb_forms
);
785 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
787 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
790 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
794 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
795 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
796 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
797 &form
.top
, &form
.right
, &form
.bottom
);
798 SAFE_FREE(dbuf
.dptr
);
799 if (ret
!= dbuf
.dsize
)
802 *list
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
804 DEBUG(0,("get_ntforms: Realloc fail.\n"));
815 /****************************************************************************
816 write a form struct list
817 ****************************************************************************/
818 int write_ntforms(nt_forms_struct
**list
, int number
)
825 for (i
=0;i
<number
;i
++) {
826 /* save index, so list is rebuilt in correct order */
827 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
828 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
829 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
831 if (len
> sizeof(buf
)) break;
832 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
833 kbuf
.dsize
= strlen(key
)+1;
837 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
843 /****************************************************************************
844 add a form struct at the end of the list
845 ****************************************************************************/
846 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
853 * NT tries to add forms even when
854 * they are already in the base
855 * only update the values if already present
860 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
861 for (n
=0; n
<*count
; n
++) {
862 if ( strequal((*list
)[n
].name
, form_name
) ) {
869 if((*list
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
870 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
873 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
877 (*list
)[n
].flag
=form
->flags
;
878 (*list
)[n
].width
=form
->size_x
;
879 (*list
)[n
].length
=form
->size_y
;
880 (*list
)[n
].left
=form
->left
;
881 (*list
)[n
].top
=form
->top
;
882 (*list
)[n
].right
=form
->right
;
883 (*list
)[n
].bottom
=form
->bottom
;
885 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
886 update
? "updated" : "added", form_name
));
891 /****************************************************************************
892 Delete a named form struct.
893 ****************************************************************************/
895 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
904 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
906 for (n
=0; n
<*count
; n
++) {
907 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
908 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
914 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
915 *ret
= WERR_INVALID_PARAM
;
919 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
920 kbuf
.dsize
= strlen(key
)+1;
922 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
930 /****************************************************************************
931 Update a form struct.
932 ****************************************************************************/
934 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
938 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
940 DEBUG(106, ("[%s]\n", form_name
));
941 for (n
=0; n
<count
; n
++) {
942 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
943 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
947 if (n
==count
) return;
949 (*list
)[n
].flag
=form
->flags
;
950 (*list
)[n
].width
=form
->size_x
;
951 (*list
)[n
].length
=form
->size_y
;
952 (*list
)[n
].left
=form
->left
;
953 (*list
)[n
].top
=form
->top
;
954 (*list
)[n
].right
=form
->right
;
955 (*list
)[n
].bottom
=form
->bottom
;
958 /****************************************************************************
959 Get the nt drivers list.
960 Traverse the database and look-up the matching names.
961 ****************************************************************************/
962 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
965 const char *short_archi
;
967 TDB_DATA kbuf
, newkey
;
969 short_archi
= get_short_archi(architecture
);
974 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
976 for (kbuf
= tdb_firstkey(tdb_drivers
);
978 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
980 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
983 if((*list
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
984 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
988 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
995 /****************************************************************************
996 Function to do the mapping between the long architecture name and
998 ****************************************************************************/
1000 const char *get_short_archi(const char *long_archi
)
1004 DEBUG(107,("Getting architecture dependant directory\n"));
1007 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
1008 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
1010 if (archi_table
[i
].long_archi
==NULL
) {
1011 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
1015 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1017 DEBUGADD(108,("index: [%d]\n", i
));
1018 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
1019 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
1021 return archi_table
[i
].short_archi
;
1024 /****************************************************************************
1025 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1026 There are two case to be covered here: PE (Portable Executable) and NE (New
1027 Executable) files. Both files support the same INFO structure, but PE files
1028 store the signature in unicode, and NE files store it as !unicode.
1029 returns -1 on error, 1 on version info found, and 0 on no version info found.
1030 ****************************************************************************/
1032 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1038 if ((buf
=(char *)SMB_MALLOC(PE_HEADER_SIZE
)) == NULL
) {
1039 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1040 fname
, PE_HEADER_SIZE
));
1044 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1045 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1046 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1047 fname
, (unsigned long)byte_count
));
1048 goto no_version_info
;
1051 /* Is this really a DOS header? */
1052 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1053 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1054 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1055 goto no_version_info
;
1058 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1059 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1060 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1062 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1063 goto no_version_info
;
1066 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
1067 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1068 fname
, (unsigned long)byte_count
));
1069 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1070 goto no_version_info
;
1073 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1074 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1075 unsigned int num_sections
;
1076 unsigned int section_table_bytes
;
1078 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
1079 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1080 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
1081 /* At this point, we assume the file is in error. It still could be somthing
1082 * else besides a PE file, but it unlikely at this point.
1087 /* get the section table */
1088 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1089 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1090 if (section_table_bytes
== 0)
1094 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
1095 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1096 fname
, section_table_bytes
));
1100 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1101 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1102 fname
, (unsigned long)byte_count
));
1106 /* Iterate the section table looking for the resource section ".rsrc" */
1107 for (i
= 0; i
< num_sections
; i
++) {
1108 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1110 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1111 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1112 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1114 if (section_bytes
== 0)
1118 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
1119 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1120 fname
, section_bytes
));
1124 /* Seek to the start of the .rsrc section info */
1125 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1126 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1131 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1132 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1133 fname
, (unsigned long)byte_count
));
1137 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1140 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1141 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1142 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1143 /* Align to next long address */
1144 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1146 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1147 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1148 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1150 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1151 fname
, *major
, *minor
,
1152 (*major
>>16)&0xffff, *major
&0xffff,
1153 (*minor
>>16)&0xffff, *minor
&0xffff));
1162 /* Version info not found, fall back to origin date/time */
1163 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1167 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1168 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1169 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1170 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1171 /* At this point, we assume the file is in error. It still could be somthing
1172 * else besides a NE file, but it unlikely at this point. */
1176 /* Allocate a bit more space to speed up things */
1178 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1179 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1180 fname
, PE_HEADER_SIZE
));
1184 /* This is a HACK! I got tired of trying to sort through the messy
1185 * 'NE' file format. If anyone wants to clean this up please have at
1186 * it, but this works. 'NE' files will eventually fade away. JRR */
1187 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1188 /* Cover case that should not occur in a well formed 'NE' .dll file */
1189 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1191 for(i
=0; i
<byte_count
; i
++) {
1192 /* Fast skip past data that can't possibly match */
1193 if (buf
[i
] != 'V') continue;
1195 /* Potential match data crosses buf boundry, move it to beginning
1196 * of buf, and fill the buf with as much as it will hold. */
1197 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1200 memcpy(buf
, &buf
[i
], byte_count
-i
);
1201 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1202 (byte_count
-i
))) < 0) {
1204 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1209 byte_count
= bc
+ (byte_count
- i
);
1210 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1215 /* Check that the full signature string and the magic number that
1216 * follows exist (not a perfect solution, but the chances that this
1217 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1218 * twice, as it is simpler to read the code. */
1219 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1220 /* Compute skip alignment to next long address */
1221 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
1222 sizeof(VS_SIGNATURE
)) & 3;
1223 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1225 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1226 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1227 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1228 fname
, *major
, *minor
,
1229 (*major
>>16)&0xffff, *major
&0xffff,
1230 (*minor
>>16)&0xffff, *minor
&0xffff));
1237 /* Version info not found, fall back to origin date/time */
1238 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1243 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1244 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1245 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1256 /****************************************************************************
1257 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1258 share one or more files. During the MS installation process files are checked
1259 to insure that only a newer version of a shared file is installed over an
1260 older version. There are several possibilities for this comparison. If there
1261 is no previous version, the new one is newer (obviously). If either file is
1262 missing the version info structure, compare the creation date (on Unix use
1263 the modification date). Otherwise chose the numerically larger version number.
1264 ****************************************************************************/
1266 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1268 BOOL use_version
= True
;
1273 time_t new_create_time
;
1277 time_t old_create_time
;
1279 files_struct
*fsp
= NULL
;
1281 SMB_STRUCT_STAT stat_buf
;
1286 SET_STAT_INVALID(st
);
1287 SET_STAT_INVALID(stat_buf
);
1288 new_create_time
= (time_t)0;
1289 old_create_time
= (time_t)0;
1291 /* Get file version info (if available) for previous file (if it exists) */
1292 pstrcpy(filepath
, old_file
);
1294 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1296 status
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1298 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1301 FILE_ATTRIBUTE_NORMAL
,
1305 if (!NT_STATUS_IS_OK(status
)) {
1306 /* Old file not found, so by definition new file is in fact newer */
1307 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1312 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1318 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1320 use_version
= False
;
1321 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1322 old_create_time
= st
.st_mtime
;
1323 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1326 close_file(fsp
, NORMAL_CLOSE
);
1328 /* Get file version info (if available) for new file */
1329 pstrcpy(filepath
, new_file
);
1330 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1332 status
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1334 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1337 FILE_ATTRIBUTE_NORMAL
,
1341 if (!NT_STATUS_IS_OK(status
)) {
1342 /* New file not found, this shouldn't occur if the caller did its job */
1343 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1348 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1354 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1356 use_version
= False
;
1357 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1358 new_create_time
= st
.st_mtime
;
1359 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1362 close_file(fsp
, NORMAL_CLOSE
);
1364 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1365 /* Compare versions and choose the larger version number */
1366 if (new_major
> old_major
||
1367 (new_major
== old_major
&& new_minor
> old_minor
)) {
1369 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1373 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1378 /* Compare modification time/dates and choose the newest time/date */
1379 if (new_create_time
> old_create_time
) {
1380 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1384 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1391 close_file(fsp
, NORMAL_CLOSE
);
1395 /****************************************************************************
1396 Determine the correct cVersion associated with an architecture and driver
1397 ****************************************************************************/
1398 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1399 struct current_user
*user
, WERROR
*perr
)
1406 files_struct
*fsp
= NULL
;
1409 connection_struct
*conn
;
1412 SET_STAT_INVALID(st
);
1414 *perr
= WERR_INVALID_PARAM
;
1416 /* If architecture is Windows 95/98/ME, the version is always 0. */
1417 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1418 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1423 /* If architecture is Windows x64, the version is always 3. */
1424 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1425 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1431 * Connect to the print$ share under the same account as the user connected
1432 * to the rpc pipe. Note we must still be root to do this.
1435 /* Null password is ok - we are already an authenticated user... */
1436 null_pw
= data_blob(NULL
, 0);
1437 fstrcpy(res_type
, "A:");
1439 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1443 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1444 *perr
= ntstatus_to_werror(nt_status
);
1448 /* We are temporarily becoming the connection user. */
1449 if (!become_user(conn
, user
->vuid
)) {
1450 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1451 *perr
= WERR_ACCESS_DENIED
;
1455 /* Open the driver file (Portable Executable format) and determine the
1456 * deriver the cversion. */
1457 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1459 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1461 if ( !vfs_file_exist( conn
, driverpath
, &st
) ) {
1462 *perr
= WERR_BADFILE
;
1466 status
= open_file_ntcreate(conn
, driverpath
, &st
,
1468 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1471 FILE_ATTRIBUTE_NORMAL
,
1475 if (!NT_STATUS_IS_OK(status
)) {
1476 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1477 driverpath
, errno
));
1478 *perr
= WERR_ACCESS_DENIED
;
1483 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1484 if (ret
== -1) goto error_exit
;
1487 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1492 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1493 * for more details. Version in this case is not just the version of the
1494 * file, but the version in the sense of kernal mode (2) vs. user mode
1495 * (3) drivers. Other bits of the version fields are the version info.
1498 cversion
= major
& 0x0000ffff;
1500 case 2: /* WinNT drivers */
1501 case 3: /* Win2K drivers */
1505 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1506 driverpath
, cversion
));
1510 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1511 driverpath
, major
, minor
));
1514 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1515 driverpath
, cversion
));
1517 close_file(fsp
, NORMAL_CLOSE
);
1518 close_cnum(conn
, user
->vuid
);
1527 close_file(fsp
, NORMAL_CLOSE
);
1529 close_cnum(conn
, user
->vuid
);
1534 /****************************************************************************
1535 ****************************************************************************/
1536 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1537 struct current_user
*user
)
1539 const char *architecture
;
1545 /* clean up the driver name.
1546 * we can get .\driver.dll
1547 * or worse c:\windows\system\driver.dll !
1549 /* using an intermediate string to not have overlaping memcpy()'s */
1550 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1551 fstrcpy(new_name
, p
+1);
1552 fstrcpy(driver
->driverpath
, new_name
);
1555 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1556 fstrcpy(new_name
, p
+1);
1557 fstrcpy(driver
->datafile
, new_name
);
1560 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1561 fstrcpy(new_name
, p
+1);
1562 fstrcpy(driver
->configfile
, new_name
);
1565 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1566 fstrcpy(new_name
, p
+1);
1567 fstrcpy(driver
->helpfile
, new_name
);
1570 if (driver
->dependentfiles
) {
1571 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1572 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1573 fstrcpy(new_name
, p
+1);
1574 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1579 architecture
= get_short_archi(driver
->environment
);
1580 if (!architecture
) {
1581 return WERR_UNKNOWN_PRINTER_DRIVER
;
1584 /* jfm:7/16/2000 the client always sends the cversion=0.
1585 * The server should check which version the driver is by reading
1586 * the PE header of driver->driverpath.
1588 * For Windows 95/98 the version is 0 (so the value sent is correct)
1589 * For Windows NT (the architecture doesn't matter)
1590 * NT 3.1: cversion=0
1591 * NT 3.5/3.51: cversion=1
1595 if ((driver
->cversion
= get_correct_cversion( architecture
, driver
->driverpath
, user
, &err
)) == -1)
1601 /****************************************************************************
1602 ****************************************************************************/
1603 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1605 const char *architecture
;
1611 /* clean up the driver name.
1612 * we can get .\driver.dll
1613 * or worse c:\windows\system\driver.dll !
1615 /* using an intermediate string to not have overlaping memcpy()'s */
1616 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1617 fstrcpy(new_name
, p
+1);
1618 fstrcpy(driver
->driverpath
, new_name
);
1621 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1622 fstrcpy(new_name
, p
+1);
1623 fstrcpy(driver
->datafile
, new_name
);
1626 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1627 fstrcpy(new_name
, p
+1);
1628 fstrcpy(driver
->configfile
, new_name
);
1631 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1632 fstrcpy(new_name
, p
+1);
1633 fstrcpy(driver
->helpfile
, new_name
);
1636 if (driver
->dependentfiles
) {
1637 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1638 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1639 fstrcpy(new_name
, p
+1);
1640 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1645 architecture
= get_short_archi(driver
->environment
);
1646 if (!architecture
) {
1647 return WERR_UNKNOWN_PRINTER_DRIVER
;
1650 /* jfm:7/16/2000 the client always sends the cversion=0.
1651 * The server should check which version the driver is by reading
1652 * the PE header of driver->driverpath.
1654 * For Windows 95/98 the version is 0 (so the value sent is correct)
1655 * For Windows NT (the architecture doesn't matter)
1656 * NT 3.1: cversion=0
1657 * NT 3.5/3.51: cversion=1
1662 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1668 /****************************************************************************
1669 ****************************************************************************/
1670 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1671 uint32 level
, struct current_user
*user
)
1676 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1677 driver
=driver_abstract
.info_3
;
1678 return clean_up_driver_struct_level_3(driver
, user
);
1682 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1683 driver
=driver_abstract
.info_6
;
1684 return clean_up_driver_struct_level_6(driver
, user
);
1687 return WERR_INVALID_PARAM
;
1691 /****************************************************************************
1692 This function sucks and should be replaced. JRA.
1693 ****************************************************************************/
1695 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1697 dst
->cversion
= src
->version
;
1699 fstrcpy( dst
->name
, src
->name
);
1700 fstrcpy( dst
->environment
, src
->environment
);
1701 fstrcpy( dst
->driverpath
, src
->driverpath
);
1702 fstrcpy( dst
->datafile
, src
->datafile
);
1703 fstrcpy( dst
->configfile
, src
->configfile
);
1704 fstrcpy( dst
->helpfile
, src
->helpfile
);
1705 fstrcpy( dst
->monitorname
, src
->monitorname
);
1706 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1707 dst
->dependentfiles
= src
->dependentfiles
;
1710 #if 0 /* Debugging function */
1712 static char* ffmt(unsigned char *c
){
1714 static char ffmt_str
[17];
1716 for (i
=0; i
<16; i
++) {
1717 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1728 /****************************************************************************
1729 ****************************************************************************/
1730 WERROR
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1731 struct current_user
*user
, WERROR
*perr
)
1733 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1735 const char *architecture
;
1740 connection_struct
*conn
;
1750 memset(inbuf
, '\0', sizeof(inbuf
));
1751 memset(outbuf
, '\0', sizeof(outbuf
));
1755 driver
=driver_abstract
.info_3
;
1756 else if (level
==6) {
1757 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1758 driver
= &converted_driver
;
1760 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1761 return WERR_UNKNOWN_LEVEL
;
1764 architecture
= get_short_archi(driver
->environment
);
1765 if (!architecture
) {
1766 return WERR_UNKNOWN_PRINTER_DRIVER
;
1770 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1771 * Note we must be root to do this.
1774 null_pw
= data_blob(NULL
, 0);
1775 fstrcpy(res_type
, "A:");
1777 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1781 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1782 *perr
= ntstatus_to_werror(nt_status
);
1783 return WERR_NO_SUCH_SHARE
;
1787 * Save who we are - we are temporarily becoming the connection user.
1790 if (!become_user(conn
, conn
->vuid
)) {
1791 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1792 return WERR_ACCESS_DENIED
;
1796 * make the directories version and version\driver_name
1797 * under the architecture directory.
1799 DEBUG(5,("Creating first directory\n"));
1800 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1801 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1802 create_directory(conn
, new_dir
);
1804 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1805 * listed for this driver which has already been moved, skip it (note:
1806 * drivers may list the same file name several times. Then check if the
1807 * file already exists in archi\cversion\, if so, check that the version
1808 * info (or time stamps if version info is unavailable) is newer (or the
1809 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1810 * Otherwise, delete the file.
1812 * If a file is not moved to archi\cversion\ because of an error, all the
1813 * rest of the 'unmoved' driver files are removed from archi\. If one or
1814 * more of the driver's files was already moved to archi\cversion\, it
1815 * potentially leaves the driver in a partially updated state. Version
1816 * trauma will most likely occur if an client attempts to use any printer
1817 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1818 * done is appropriate... later JRR
1821 DEBUG(5,("Moving files now !\n"));
1823 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1824 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1825 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1826 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1827 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1828 if ( !NT_STATUS_IS_OK(copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1829 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
))) {
1830 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1831 new_name
, old_name
));
1832 *perr
= WERR_ACCESS_DENIED
;
1838 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1839 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1840 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1841 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1842 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1843 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1844 if ( !NT_STATUS_IS_OK(copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1845 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
))) {
1846 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1847 new_name
, old_name
));
1848 *perr
= WERR_ACCESS_DENIED
;
1855 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1856 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1857 !strequal(driver
->configfile
, driver
->datafile
)) {
1858 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1859 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1860 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1861 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1862 if ( !NT_STATUS_IS_OK(copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1863 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
))) {
1864 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1865 new_name
, old_name
));
1866 *perr
= WERR_ACCESS_DENIED
;
1873 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1874 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1875 !strequal(driver
->helpfile
, driver
->datafile
) &&
1876 !strequal(driver
->helpfile
, driver
->configfile
)) {
1877 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1878 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1879 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1880 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1881 if ( !NT_STATUS_IS_OK(copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1882 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
))) {
1883 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1884 new_name
, old_name
));
1885 *perr
= WERR_ACCESS_DENIED
;
1892 if (driver
->dependentfiles
) {
1893 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1894 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1895 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1896 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1897 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1899 for (j
=0; j
< i
; j
++) {
1900 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1905 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1906 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1907 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1908 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1909 if ( !NT_STATUS_IS_OK(copy_file(new_name
, old_name
, conn
,
1910 OPENX_FILE_EXISTS_TRUNCATE
|
1911 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
))) {
1912 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1913 new_name
, old_name
));
1914 *perr
= WERR_ACCESS_DENIED
;
1923 close_cnum(conn
, user
->vuid
);
1926 return ver
!= -1 ? WERR_OK
: WERR_UNKNOWN_PRINTER_DRIVER
;
1929 /****************************************************************************
1930 ****************************************************************************/
1931 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1934 const char *architecture
;
1940 TDB_DATA kbuf
, dbuf
;
1942 architecture
= get_short_archi(driver
->environment
);
1943 if (!architecture
) {
1947 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1948 * \\server is added in the rpc server layer.
1949 * It does make sense to NOT store the server's name in the printer TDB.
1952 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1954 /* .inf files do not always list a file for each of the four standard files.
1955 * Don't prepend a path to a null filename, or client claims:
1956 * "The server on which the printer resides does not have a suitable
1957 * <printer driver name> printer driver installed. Click OK if you
1958 * wish to install the driver on your local machine."
1960 if (strlen(driver
->driverpath
)) {
1961 fstrcpy(temp_name
, driver
->driverpath
);
1962 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1965 if (strlen(driver
->datafile
)) {
1966 fstrcpy(temp_name
, driver
->datafile
);
1967 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1970 if (strlen(driver
->configfile
)) {
1971 fstrcpy(temp_name
, driver
->configfile
);
1972 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1975 if (strlen(driver
->helpfile
)) {
1976 fstrcpy(temp_name
, driver
->helpfile
);
1977 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1980 if (driver
->dependentfiles
) {
1981 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1982 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1983 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1987 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1989 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1996 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1999 driver
->environment
,
2004 driver
->monitorname
,
2005 driver
->defaultdatatype
);
2007 if (driver
->dependentfiles
) {
2008 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
2009 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
2010 driver
->dependentfiles
[i
]);
2014 if (len
!= buflen
) {
2015 buf
= (char *)SMB_REALLOC(buf
, len
);
2017 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2027 kbuf
.dsize
= strlen(key
)+1;
2031 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
2035 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
2041 /****************************************************************************
2042 ****************************************************************************/
2043 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
2045 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
2048 info3
.cversion
= driver
->version
;
2049 fstrcpy(info3
.name
,driver
->name
);
2050 fstrcpy(info3
.environment
,driver
->environment
);
2051 fstrcpy(info3
.driverpath
,driver
->driverpath
);
2052 fstrcpy(info3
.datafile
,driver
->datafile
);
2053 fstrcpy(info3
.configfile
,driver
->configfile
);
2054 fstrcpy(info3
.helpfile
,driver
->helpfile
);
2055 fstrcpy(info3
.monitorname
,driver
->monitorname
);
2056 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
2057 info3
.dependentfiles
= driver
->dependentfiles
;
2059 return add_a_printer_driver_3(&info3
);
2063 /****************************************************************************
2064 ****************************************************************************/
2065 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
2067 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
2071 fstrcpy(info
.name
, driver
);
2072 fstrcpy(info
.defaultdatatype
, "RAW");
2074 fstrcpy(info
.driverpath
, "");
2075 fstrcpy(info
.datafile
, "");
2076 fstrcpy(info
.configfile
, "");
2077 fstrcpy(info
.helpfile
, "");
2079 if ((info
.dependentfiles
= SMB_MALLOC_ARRAY(fstring
, 2)) == NULL
)
2082 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
2083 fstrcpy(info
.dependentfiles
[0], "");
2085 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&info
, sizeof(info
));
2087 SAFE_FREE(info
.dependentfiles
);
2094 /****************************************************************************
2095 ****************************************************************************/
2096 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
2098 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
2099 TDB_DATA kbuf
, dbuf
;
2100 const char *architecture
;
2105 ZERO_STRUCT(driver
);
2107 architecture
= get_short_archi(arch
);
2108 if ( !architecture
) {
2109 return WERR_UNKNOWN_PRINTER_DRIVER
;
2112 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2114 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2117 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2119 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
2122 kbuf
.dsize
= strlen(key
)+1;
2124 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
2126 return WERR_UNKNOWN_PRINTER_DRIVER
;
2128 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2137 driver
.defaultdatatype
);
2140 while (len
< dbuf
.dsize
) {
2141 driver
.dependentfiles
= SMB_REALLOC_ARRAY(driver
.dependentfiles
, fstring
, i
+2);
2142 if ( !driver
.dependentfiles
) {
2143 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2147 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2148 &driver
.dependentfiles
[i
]);
2152 if ( driver
.dependentfiles
)
2153 fstrcpy( driver
.dependentfiles
[i
], "" );
2155 SAFE_FREE(dbuf
.dptr
);
2157 if (len
!= dbuf
.dsize
) {
2158 SAFE_FREE(driver
.dependentfiles
);
2160 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
2163 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
2165 SAFE_FREE(driver
.dependentfiles
);
2172 /****************************************************************************
2173 Debugging function, dump at level 6 the struct in the logs.
2174 ****************************************************************************/
2176 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2179 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
2182 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
2188 if (driver
.info_3
== NULL
)
2191 info3
=driver
.info_3
;
2193 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
2194 DEBUGADD(20,("name:[%s]\n", info3
->name
));
2195 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
2196 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
2197 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
2198 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
2199 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
2200 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
2201 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
2203 for (i
=0; info3
->dependentfiles
&&
2204 *info3
->dependentfiles
[i
]; i
++) {
2205 DEBUGADD(20,("dependentfile:[%s]\n",
2206 info3
->dependentfiles
[i
]));
2213 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
2221 /****************************************************************************
2222 ****************************************************************************/
2223 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
2227 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2232 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2233 nt_devmode
->devicename
,
2234 nt_devmode
->formname
,
2236 nt_devmode
->specversion
,
2237 nt_devmode
->driverversion
,
2239 nt_devmode
->driverextra
,
2240 nt_devmode
->orientation
,
2241 nt_devmode
->papersize
,
2242 nt_devmode
->paperlength
,
2243 nt_devmode
->paperwidth
,
2246 nt_devmode
->defaultsource
,
2247 nt_devmode
->printquality
,
2250 nt_devmode
->yresolution
,
2251 nt_devmode
->ttoption
,
2252 nt_devmode
->collate
,
2253 nt_devmode
->logpixels
,
2256 nt_devmode
->bitsperpel
,
2257 nt_devmode
->pelswidth
,
2258 nt_devmode
->pelsheight
,
2259 nt_devmode
->displayflags
,
2260 nt_devmode
->displayfrequency
,
2261 nt_devmode
->icmmethod
,
2262 nt_devmode
->icmintent
,
2263 nt_devmode
->mediatype
,
2264 nt_devmode
->dithertype
,
2265 nt_devmode
->reserved1
,
2266 nt_devmode
->reserved2
,
2267 nt_devmode
->panningwidth
,
2268 nt_devmode
->panningheight
,
2269 nt_devmode
->nt_dev_private
);
2272 if (nt_devmode
->nt_dev_private
) {
2273 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2274 nt_devmode
->driverextra
,
2275 nt_devmode
->nt_dev_private
);
2278 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2283 /****************************************************************************
2284 Pack all values in all printer keys
2285 ***************************************************************************/
2287 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2291 REGISTRY_VALUE
*val
;
2292 REGVAL_CTR
*val_ctr
;
2299 /* loop over all keys */
2301 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2302 val_ctr
= data
->keys
[i
].values
;
2303 num_values
= regval_ctr_numvals( val_ctr
);
2305 /* pack the keyname followed by a empty value */
2307 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2308 &data
->keys
[i
].name
,
2314 /* now loop over all values */
2316 for ( j
=0; j
<num_values
; j
++ ) {
2317 /* pathname should be stored as <key>\<value> */
2319 val
= regval_ctr_specific_value( val_ctr
, j
);
2320 pstrcpy( path
, data
->keys
[i
].name
);
2321 pstrcat( path
, "\\" );
2322 pstrcat( path
, regval_name(val
) );
2324 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2329 regval_data_p(val
) );
2331 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2338 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2344 /****************************************************************************
2345 Delete a printer - this just deletes the printer info file, any open
2346 handles are not affected.
2347 ****************************************************************************/
2349 uint32
del_a_printer(const char *sharename
)
2352 pstring printdb_path
;
2354 kbuf
= make_printer_tdbkey( sharename
);
2355 tdb_delete(tdb_printers
, kbuf
);
2357 kbuf
.dptr
= make_printers_secdesc_tdbkey( sharename
);
2358 kbuf
.dsize
= strlen(kbuf
.dptr
) + 1;
2359 tdb_delete(tdb_printers
, kbuf
);
2361 close_all_print_db();
2363 if (geteuid() == 0) {
2364 pstrcpy(printdb_path
, lock_path("printing/"));
2365 pstrcat(printdb_path
, sharename
);
2366 pstrcat(printdb_path
, ".tdb");
2368 unlink(printdb_path
);
2374 /****************************************************************************
2375 ****************************************************************************/
2376 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2381 TDB_DATA kbuf
, dbuf
;
2384 * in addprinter: no servername and the printer is the name
2385 * in setprinter: servername is \\server
2386 * and printer is \\server\\printer
2388 * Samba manages only local printers.
2389 * we currently don't support things like i
2390 * path=\\other_server\printer
2392 * We only store the printername, not \\server\printername
2395 if ( info
->servername
[0] != '\0' ) {
2396 trim_string(info
->printername
, info
->servername
, NULL
);
2397 trim_char(info
->printername
, '\\', '\0');
2398 info
->servername
[0]='\0';
2402 * JFM: one day I'll forget.
2403 * below that's info->portname because that's the SAMBA sharename
2404 * and I made NT 'thinks' it's the portname
2405 * the info->sharename is the thing you can name when you add a printer
2406 * that's the short-name when you create shared printer for 95/98
2407 * So I've made a limitation in SAMBA: you can only have 1 printer model
2408 * behind a SAMBA share.
2416 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2419 info
->default_priority
,
2436 info
->printprocessor
,
2440 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2442 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
2444 if (buflen
!= len
) {
2445 buf
= (char *)SMB_REALLOC(buf
, len
);
2447 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2456 kbuf
= make_printer_tdbkey( info
->sharename
);
2461 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2464 if (!W_ERROR_IS_OK(ret
))
2465 DEBUG(8, ("error updating printer to tdb on disk\n"));
2469 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2470 info
->sharename
, info
->drivername
, info
->portname
, len
));
2476 /****************************************************************************
2477 Malloc and return an NT devicemode.
2478 ****************************************************************************/
2480 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2483 char adevice
[MAXDEVICENAME
];
2484 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2486 if (nt_devmode
== NULL
) {
2487 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2491 ZERO_STRUCTP(nt_devmode
);
2493 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2494 fstrcpy(nt_devmode
->devicename
, adevice
);
2496 fstrcpy(nt_devmode
->formname
, "Letter");
2498 nt_devmode
->specversion
= 0x0401;
2499 nt_devmode
->driverversion
= 0x0400;
2500 nt_devmode
->size
= 0x00DC;
2501 nt_devmode
->driverextra
= 0x0000;
2502 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2503 DEFAULTSOURCE
| COPIES
| SCALE
|
2504 PAPERSIZE
| ORIENTATION
;
2505 nt_devmode
->orientation
= 1;
2506 nt_devmode
->papersize
= PAPER_LETTER
;
2507 nt_devmode
->paperlength
= 0;
2508 nt_devmode
->paperwidth
= 0;
2509 nt_devmode
->scale
= 0x64;
2510 nt_devmode
->copies
= 1;
2511 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2512 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2513 nt_devmode
->color
= COLOR_MONOCHROME
;
2514 nt_devmode
->duplex
= DUP_SIMPLEX
;
2515 nt_devmode
->yresolution
= 0;
2516 nt_devmode
->ttoption
= TT_SUBDEV
;
2517 nt_devmode
->collate
= COLLATE_FALSE
;
2518 nt_devmode
->icmmethod
= 0;
2519 nt_devmode
->icmintent
= 0;
2520 nt_devmode
->mediatype
= 0;
2521 nt_devmode
->dithertype
= 0;
2523 /* non utilisés par un driver d'imprimante */
2524 nt_devmode
->logpixels
= 0;
2525 nt_devmode
->bitsperpel
= 0;
2526 nt_devmode
->pelswidth
= 0;
2527 nt_devmode
->pelsheight
= 0;
2528 nt_devmode
->displayflags
= 0;
2529 nt_devmode
->displayfrequency
= 0;
2530 nt_devmode
->reserved1
= 0;
2531 nt_devmode
->reserved2
= 0;
2532 nt_devmode
->panningwidth
= 0;
2533 nt_devmode
->panningheight
= 0;
2535 nt_devmode
->nt_dev_private
= NULL
;
2539 /****************************************************************************
2540 Deepcopy an NT devicemode.
2541 ****************************************************************************/
2543 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2545 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2547 if ( !nt_devicemode
)
2550 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2551 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2555 new_nt_devicemode
->nt_dev_private
= NULL
;
2556 if (nt_devicemode
->nt_dev_private
!= NULL
) {
2557 if ((new_nt_devicemode
->nt_dev_private
= (uint8
*)memdup(nt_devicemode
->nt_dev_private
, nt_devicemode
->driverextra
)) == NULL
) {
2558 SAFE_FREE(new_nt_devicemode
);
2559 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2564 return new_nt_devicemode
;
2567 /****************************************************************************
2568 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2569 ****************************************************************************/
2571 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2573 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2575 if(nt_devmode
== NULL
)
2578 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2580 SAFE_FREE(nt_devmode
->nt_dev_private
);
2581 SAFE_FREE(*devmode_ptr
);
2584 /****************************************************************************
2585 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2586 ****************************************************************************/
2588 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2590 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2595 free_nt_devicemode(&info
->devmode
);
2597 TALLOC_FREE( *info_ptr
);
2601 /****************************************************************************
2602 ****************************************************************************/
2603 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2607 NT_DEVICEMODE devmode
;
2609 ZERO_STRUCT(devmode
);
2611 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2613 if (!*nt_devmode
) return len
;
2615 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2619 &devmode
.specversion
,
2620 &devmode
.driverversion
,
2622 &devmode
.driverextra
,
2623 &devmode
.orientation
,
2625 &devmode
.paperlength
,
2626 &devmode
.paperwidth
,
2629 &devmode
.defaultsource
,
2630 &devmode
.printquality
,
2633 &devmode
.yresolution
,
2639 &devmode
.bitsperpel
,
2641 &devmode
.pelsheight
,
2642 &devmode
.displayflags
,
2643 &devmode
.displayfrequency
,
2647 &devmode
.dithertype
,
2650 &devmode
.panningwidth
,
2651 &devmode
.panningheight
,
2652 &devmode
.nt_dev_private
);
2654 if (devmode
.nt_dev_private
) {
2655 /* the len in tdb_unpack is an int value and
2656 * devmode.driverextra is only a short
2658 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2659 devmode
.driverextra
=(uint16
)extra_len
;
2661 /* check to catch an invalid TDB entry so we don't segfault */
2662 if (devmode
.driverextra
== 0) {
2663 devmode
.nt_dev_private
= NULL
;
2667 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2669 SAFE_FREE(devmode
.nt_dev_private
);
2673 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2674 if (devmode
.nt_dev_private
)
2675 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2680 /****************************************************************************
2681 Allocate and initialize a new slot.
2682 ***************************************************************************/
2684 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2689 if ( !name
|| !data
)
2692 /* allocate another slot in the NT_PRINTER_KEY array */
2694 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2695 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2701 key_index
= data
->num_keys
;
2703 /* initialze new key */
2705 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2707 if ( !(data
->keys
[key_index
].values
= TALLOC_ZERO_P( data
, REGVAL_CTR
)) )
2712 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2717 /****************************************************************************
2718 search for a registry key name in the existing printer data
2719 ***************************************************************************/
2721 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2725 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2726 if ( strequal( data
->keys
[i
].name
, name
) ) {
2728 /* cleanup memory */
2730 TALLOC_FREE( data
->keys
[i
].name
);
2731 TALLOC_FREE( data
->keys
[i
].values
);
2733 /* if not the end of the array, move remaining elements down one slot */
2736 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2737 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2744 return data
->num_keys
;
2747 /****************************************************************************
2748 search for a registry key name in the existing printer data
2749 ***************************************************************************/
2751 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2756 if ( !data
|| !name
)
2759 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2761 /* loop over all existing keys */
2763 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2764 if ( strequal(data
->keys
[i
].name
, name
) ) {
2765 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2775 /****************************************************************************
2776 ***************************************************************************/
2778 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2782 int num_subkeys
= 0;
2784 fstring
*subkeys_ptr
= NULL
;
2795 /* special case of asking for the top level printer data registry key names */
2797 if ( strlen(key
) == 0 ) {
2798 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2800 /* found a match, so allocate space and copy the name */
2802 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2803 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2808 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2815 /* asking for the subkeys of some key */
2816 /* subkey paths are stored in the key name using '\' as the delimiter */
2818 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2819 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2821 /* if we found the exact key, then break */
2822 key_len
= strlen( key
);
2823 if ( strlen(data
->keys
[i
].name
) == key_len
)
2826 /* get subkey path */
2828 p
= data
->keys
[i
].name
+ key_len
;
2831 fstrcpy( subkeyname
, p
);
2832 if ( (p
= strchr( subkeyname
, '\\' )) )
2835 /* don't add a key more than once */
2837 for ( j
=0; j
<num_subkeys
; j
++ ) {
2838 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2842 if ( j
!= num_subkeys
)
2845 /* found a match, so allocate space and copy the name */
2847 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2848 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2853 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2859 /* return error if the key was not found */
2861 if ( i
== data
->num_keys
) {
2862 SAFE_FREE(subkeys_ptr
);
2867 /* tag off the end */
2870 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2872 *subkeys
= subkeys_ptr
;
2878 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2881 smb_ucs2_t conv_str
[1024];
2884 regval_ctr_delvalue(ctr
, val_name
);
2885 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2886 STR_TERMINATE
| STR_NOALIGN
);
2887 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2888 (char *) conv_str
, str_size
);
2891 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2894 regval_ctr_delvalue(ctr
, val_name
);
2895 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2896 (char *) &dword
, sizeof(dword
));
2899 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2902 uint8 bin_bool
= (b
? 1 : 0);
2903 regval_ctr_delvalue(ctr
, val_name
);
2904 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2905 (char *) &bin_bool
, sizeof(bin_bool
));
2908 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2909 const char *multi_sz
)
2911 smb_ucs2_t
*conv_strs
= NULL
;
2914 /* a multi-sz has to have a null string terminator, i.e., the last
2915 string must be followed by two nulls */
2916 str_size
= strlen(multi_sz
) + 2;
2917 conv_strs
= SMB_CALLOC_ARRAY(smb_ucs2_t
, str_size
);
2922 /* Change to byte units. */
2923 str_size
*= sizeof(smb_ucs2_t
);
2924 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2925 STR_TERMINATE
| STR_NOALIGN
);
2927 regval_ctr_delvalue(ctr
, val_name
);
2928 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2929 (char *) conv_strs
, str_size
);
2930 safe_free(conv_strs
);
2934 /****************************************************************************
2935 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2937 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2938 * @return BOOL indicating success or failure
2939 ***************************************************************************/
2941 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2943 REGVAL_CTR
*ctr
= NULL
;
2946 char *allocated_string
= NULL
;
2947 const char *ascii_str
;
2950 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2951 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
2952 ctr
= info2
->data
->keys
[i
].values
;
2954 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2955 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2957 /* we make the assumption that the netbios name is the same
2958 as the DNS name sinc ethe former will be what we used to
2961 if ( get_mydnsdomname( dnssuffix
) )
2962 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2964 fstrcpy( longname
, global_myname() );
2966 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2968 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2969 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2970 SAFE_FREE(allocated_string
);
2972 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2973 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2974 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2975 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2976 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2977 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2978 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2979 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2980 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2982 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2983 (info2
->attributes
&
2984 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2986 switch (info2
->attributes
& 0x3) {
2988 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2991 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2994 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2997 ascii_str
= "unknown";
2999 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
3004 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
3008 REGVAL_CTR
*ctr
=NULL
;
3010 /* find the DsSpooler key */
3011 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3012 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3013 ctr
= info2
->data
->keys
[i
].values
;
3015 regval_ctr_delvalue(ctr
, "objectGUID");
3016 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
3017 (char *) &guid
, sizeof(struct GUID
));
3020 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
3021 NT_PRINTER_INFO_LEVEL
*printer
)
3025 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
3026 char *srv_dn_utf8
, **srv_cn_utf8
;
3029 const char *attrs
[] = {"objectGUID", NULL
};
3031 WERROR win_rc
= WERR_OK
;
3033 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
3035 /* figure out where to publish */
3036 ads_find_machine_acct(ads
, &res
, global_myname());
3038 /* We use ldap_get_dn here as we need the answer
3039 * in utf8 to call ldap_explode_dn(). JRA. */
3041 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ld
, (LDAPMessage
*)res
);
3044 return WERR_SERVER_UNAVAILABLE
;
3046 ads_msgfree(ads
, res
);
3047 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3049 ldap_memfree(srv_dn_utf8
);
3051 return WERR_SERVER_UNAVAILABLE
;
3053 /* Now convert to CH_UNIX. */
3054 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
3055 ldap_memfree(srv_dn_utf8
);
3056 ldap_memfree(srv_cn_utf8
);
3058 return WERR_SERVER_UNAVAILABLE
;
3060 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
3061 ldap_memfree(srv_dn_utf8
);
3062 ldap_memfree(srv_cn_utf8
);
3065 return WERR_SERVER_UNAVAILABLE
;
3068 ldap_memfree(srv_dn_utf8
);
3069 ldap_memfree(srv_cn_utf8
);
3071 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
3072 printer
->info_2
->sharename
, srv_dn
);
3075 SAFE_FREE(srv_cn_0
);
3077 /* build the ads mods */
3078 ctx
= talloc_init("nt_printer_publish_ads");
3084 mods
= ads_init_mods(ctx
);
3088 talloc_destroy(ctx
);
3092 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3093 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3094 printer
->info_2
->sharename
);
3097 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3098 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
)
3099 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3101 if (!ADS_ERR_OK(ads_rc
))
3102 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3104 talloc_destroy(ctx
);
3106 /* retreive the guid and store it locally */
3107 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3109 ads_pull_guid(ads
, res
, &guid
);
3110 ads_msgfree(ads
, res
);
3111 store_printer_guid(printer
->info_2
, guid
);
3112 win_rc
= mod_a_printer(printer
, 2);
3119 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3120 NT_PRINTER_INFO_LEVEL
*printer
)
3124 char *prt_dn
= NULL
;
3126 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3128 /* remove the printer from the directory */
3129 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3130 printer
->info_2
->sharename
, global_myname());
3132 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
3133 prt_dn
= ads_get_dn(ads
, res
);
3135 ads_msgfree(ads
, res
);
3138 ads_rc
= ads_del_dn(ads
, prt_dn
);
3139 ads_memfree(ads
, prt_dn
);
3142 ads_msgfree(ads
, res
);
3146 /****************************************************************************
3147 * Publish a printer in the directory
3149 * @param snum describing printer service
3150 * @return WERROR indicating status of publishing
3151 ***************************************************************************/
3153 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3156 ADS_STRUCT
*ads
= NULL
;
3157 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3160 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3161 if (!W_ERROR_IS_OK(win_rc
))
3165 case SPOOL_DS_PUBLISH
:
3166 case SPOOL_DS_UPDATE
:
3167 /* set the DsSpooler info and attributes */
3168 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3169 win_rc
= WERR_NOMEM
;
3173 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3175 case SPOOL_DS_UNPUBLISH
:
3176 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3179 win_rc
= WERR_NOT_SUPPORTED
;
3183 win_rc
= mod_a_printer(printer
, 2);
3184 if (!W_ERROR_IS_OK(win_rc
)) {
3185 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3189 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3191 DEBUG(3, ("ads_init() failed\n"));
3192 win_rc
= WERR_SERVER_UNAVAILABLE
;
3195 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3196 SAFE_FREE(ads
->auth
.password
);
3197 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3200 /* ads_connect() will find the DC for us */
3201 ads_rc
= ads_connect(ads
);
3202 if (!ADS_ERR_OK(ads_rc
)) {
3203 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3204 win_rc
= WERR_ACCESS_DENIED
;
3209 case SPOOL_DS_PUBLISH
:
3210 case SPOOL_DS_UPDATE
:
3211 win_rc
= nt_printer_publish_ads(ads
, printer
);
3213 case SPOOL_DS_UNPUBLISH
:
3214 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3219 free_a_printer(&printer
, 2);
3224 WERROR
check_published_printers(void)
3227 ADS_STRUCT
*ads
= NULL
;
3229 int n_services
= lp_numservices();
3230 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3232 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3234 DEBUG(3, ("ads_init() failed\n"));
3235 return WERR_SERVER_UNAVAILABLE
;
3237 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3238 SAFE_FREE(ads
->auth
.password
);
3239 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3242 /* ads_connect() will find the DC for us */
3243 ads_rc
= ads_connect(ads
);
3244 if (!ADS_ERR_OK(ads_rc
)) {
3245 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3247 return WERR_ACCESS_DENIED
;
3250 for (snum
= 0; snum
< n_services
; snum
++) {
3251 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3254 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3255 lp_servicename(snum
))) &&
3256 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3257 nt_printer_publish_ads(ads
, printer
);
3259 free_a_printer(&printer
, 2);
3266 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3269 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3271 REGISTRY_VALUE
*guid_val
;
3275 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3277 if (!W_ERROR_IS_OK(win_rc
) ||
3278 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3279 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3280 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3281 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3283 free_a_printer(&printer
, 2);
3287 /* fetching printer guids really ought to be a separate function.. */
3288 if (guid
&& regval_size(guid_val
) == sizeof(struct GUID
))
3289 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct GUID
));
3291 free_a_printer(&printer
, 2);
3295 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3300 WERROR
check_published_printers(void)
3305 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3310 #endif /* HAVE_ADS */
3312 /****************************************************************************
3313 ***************************************************************************/
3315 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3317 NT_PRINTER_DATA
*data
;
3319 int removed_keys
= 0;
3323 empty_slot
= data
->num_keys
;
3326 return WERR_INVALID_PARAM
;
3328 /* remove all keys */
3330 if ( !strlen(key
) ) {
3332 TALLOC_FREE( data
);
3336 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3342 /* remove a specific key (and all subkeys) */
3344 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3345 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3346 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3347 data
->keys
[i
].name
));
3349 TALLOC_FREE( data
->keys
[i
].name
);
3350 TALLOC_FREE( data
->keys
[i
].values
);
3352 /* mark the slot as empty */
3354 ZERO_STRUCTP( &data
->keys
[i
] );
3358 /* find the first empty slot */
3360 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3361 if ( !data
->keys
[i
].name
) {
3368 if ( i
== data
->num_keys
)
3369 /* nothing was removed */
3370 return WERR_INVALID_PARAM
;
3372 /* move everything down */
3374 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3375 if ( data
->keys
[i
].name
) {
3376 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3377 ZERO_STRUCTP( &data
->keys
[i
] );
3385 data
->num_keys
-= removed_keys
;
3387 /* sanity check to see if anything is left */
3389 if ( !data
->num_keys
) {
3390 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3392 SAFE_FREE( data
->keys
);
3393 ZERO_STRUCTP( data
);
3399 /****************************************************************************
3400 ***************************************************************************/
3402 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3404 WERROR result
= WERR_OK
;
3407 /* we must have names on non-zero length */
3409 if ( !key
|| !*key
|| !value
|| !*value
)
3410 return WERR_INVALID_NAME
;
3412 /* find the printer key first */
3414 key_index
= lookup_printerkey( p2
->data
, key
);
3415 if ( key_index
== -1 )
3418 /* make sure the value exists so we can return the correct error code */
3420 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3421 return WERR_BADFILE
;
3423 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3425 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3431 /****************************************************************************
3432 ***************************************************************************/
3434 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3435 uint32 type
, uint8
*data
, int real_len
)
3437 WERROR result
= WERR_OK
;
3440 /* we must have names on non-zero length */
3442 if ( !key
|| !*key
|| !value
|| !*value
)
3443 return WERR_INVALID_NAME
;
3445 /* find the printer key first */
3447 key_index
= lookup_printerkey( p2
->data
, key
);
3448 if ( key_index
== -1 )
3449 key_index
= add_new_printer_key( p2
->data
, key
);
3451 if ( key_index
== -1 )
3454 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3455 type
, (const char *)data
, real_len
);
3457 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3458 key
, value
, type
, real_len
));
3463 /****************************************************************************
3464 ***************************************************************************/
3466 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3470 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3473 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3476 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3479 /****************************************************************************
3480 Unpack a list of registry values frem the TDB
3481 ***************************************************************************/
3483 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3487 pstring string
, valuename
, keyname
;
3491 REGISTRY_VALUE
*regval_p
;
3494 /* add the "PrinterDriverData" key first for performance reasons */
3496 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3498 /* loop and unpack the rest of the registry values */
3502 /* check to see if there are any more registry values */
3505 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3509 /* unpack the next regval */
3511 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3517 /* lookup for subkey names which have a type of REG_NONE */
3518 /* there's no data with this entry */
3520 if ( type
== REG_NONE
) {
3521 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3522 add_new_printer_key( printer_data
, string
);
3527 * break of the keyname from the value name.
3528 * Valuenames can have embedded '\'s so be careful.
3529 * only support one level of keys. See the
3530 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3534 str
= strchr_m( string
, '\\');
3536 /* Put in "PrinterDriverData" is no key specified */
3539 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3540 pstrcpy( valuename
, string
);
3544 pstrcpy( keyname
, string
);
3545 pstrcpy( valuename
, str
+1 );
3548 /* see if we need a new key */
3550 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3551 key_index
= add_new_printer_key( printer_data
, keyname
);
3553 if ( key_index
== -1 ) {
3554 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3559 /* add the new value */
3561 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3563 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3565 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3571 /****************************************************************************
3572 ***************************************************************************/
3574 static void map_to_os2_driver(fstring drivername
)
3576 static BOOL initialised
=False
;
3577 static fstring last_from
,last_to
;
3578 char *mapfile
= lp_os2_driver_map();
3579 char **lines
= NULL
;
3583 if (!strlen(drivername
))
3590 *last_from
= *last_to
= 0;
3594 if (strequal(drivername
,last_from
)) {
3595 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3596 fstrcpy(drivername
,last_to
);
3600 lines
= file_lines_load(mapfile
, &numlines
,0);
3601 if (numlines
== 0 || lines
== NULL
) {
3602 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3607 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3609 for( i
= 0; i
< numlines
; i
++) {
3610 char *nt_name
= lines
[i
];
3611 char *os2_name
= strchr(nt_name
,'=');
3618 while (isspace(*nt_name
))
3621 if (!*nt_name
|| strchr("#;",*nt_name
))
3625 int l
= strlen(nt_name
);
3626 while (l
&& isspace(nt_name
[l
-1])) {
3632 while (isspace(*os2_name
))
3636 int l
= strlen(os2_name
);
3637 while (l
&& isspace(os2_name
[l
-1])) {
3643 if (strequal(nt_name
,drivername
)) {
3644 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3645 fstrcpy(last_from
,drivername
);
3646 fstrcpy(last_to
,os2_name
);
3647 fstrcpy(drivername
,os2_name
);
3648 file_lines_free(lines
);
3653 file_lines_free(lines
);
3656 /****************************************************************************
3657 Get a default printer info 2 struct.
3658 ****************************************************************************/
3659 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char* sharename
)
3663 snum
= lp_servicenumber(sharename
);
3665 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3666 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
3667 servername
, sharename
);
3668 fstrcpy(info
->sharename
, sharename
);
3669 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
3671 /* by setting the driver name to an empty string, a local NT admin
3672 can now run the **local** APW to install a local printer driver
3673 for a Samba shared printer in 2.2. Without this, drivers **must** be
3674 installed on the Samba server for NT clients --jerry */
3675 #if 0 /* JERRY --do not uncomment-- */
3676 if (!*info
->drivername
)
3677 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3681 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
3683 pstrcpy(info
->comment
, "");
3684 fstrcpy(info
->printprocessor
, "winprint");
3685 fstrcpy(info
->datatype
, "RAW");
3687 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3689 info
->starttime
= 0; /* Minutes since 12:00am GMT */
3690 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
3692 info
->default_priority
= 1;
3693 info
->setuptime
= (uint32
)time(NULL
);
3696 * I changed this as I think it is better to have a generic
3697 * DEVMODE than to crash Win2k explorer.exe --jerry
3698 * See the HP Deskjet 990c Win2k drivers for an example.
3700 * However the default devmode appears to cause problems
3701 * with the HP CLJ 8500 PCL driver. Hence the addition of
3702 * the "default devmode" parameter --jerry 22/01/2002
3705 if (lp_default_devmode(snum
)) {
3706 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
) {
3710 info
->devmode
= NULL
;
3713 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
3721 free_nt_devicemode(&info
->devmode
);
3723 return WERR_ACCESS_DENIED
;
3726 /****************************************************************************
3727 ****************************************************************************/
3728 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char *sharename
)
3731 int snum
= lp_servicenumber(sharename
);
3732 TDB_DATA kbuf
, dbuf
;
3733 fstring printername
;
3734 char adevice
[MAXDEVICENAME
];
3736 kbuf
= make_printer_tdbkey( sharename
);
3738 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3740 return get_a_printer_2_default(info
, servername
, sharename
);
3743 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3746 &info
->default_priority
,
3753 &info
->c_setprinter
,
3763 info
->printprocessor
,
3767 /* Samba has to have shared raw drivers. */
3768 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3769 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3771 /* Restore the stripped strings. */
3772 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3774 if ( lp_force_printername(snum
) ) {
3775 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3777 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
3780 fstrcpy(info
->printername
, printername
);
3782 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3785 * Some client drivers freak out if there is a NULL devmode
3786 * (probably the driver is not checking before accessing
3787 * the devmode pointer) --jerry
3789 * See comments in get_a_printer_2_default()
3792 if (lp_default_devmode(snum
) && !info
->devmode
) {
3793 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3795 info
->devmode
= construct_nt_devicemode(printername
);
3798 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
3799 if (info
->devmode
) {
3800 fstrcpy(info
->devmode
->devicename
, adevice
);
3803 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
3804 DEBUG(0,("unpack_values: talloc() failed!\n"));
3805 SAFE_FREE(dbuf
.dptr
);
3808 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3810 /* This will get the current RPC talloc context, but we should be
3811 passing this as a parameter... fixme... JRA ! */
3813 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
3814 SAFE_FREE(dbuf
.dptr
);
3818 /* Fix for OS/2 drivers. */
3820 if (get_remote_arch() == RA_OS2
) {
3821 map_to_os2_driver(info
->drivername
);
3824 SAFE_FREE(dbuf
.dptr
);
3826 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3827 sharename
, info
->printername
, info
->drivername
));
3832 /****************************************************************************
3833 Debugging function, dump at level 6 the struct in the logs.
3834 ****************************************************************************/
3835 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3838 NT_PRINTER_INFO_LEVEL_2
*info2
;
3840 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3845 if (printer
->info_2
== NULL
)
3849 info2
=printer
->info_2
;
3851 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3852 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3853 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3854 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3855 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3856 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3857 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3858 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3859 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3860 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3861 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3863 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3864 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3865 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3866 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3867 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3868 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3869 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3870 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3871 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3872 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3873 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3879 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3887 /****************************************************************************
3888 Update the changeid time.
3889 This is SO NASTY as some drivers need this to change, others need it
3890 static. This value will change every second, and I must hope that this
3891 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3893 ****************************************************************************/
3895 static uint32
rev_changeid(void)
3899 get_process_uptime(&tv
);
3902 /* Return changeid as msec since spooler restart */
3903 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3906 * This setting seems to work well but is too untested
3907 * to replace the above calculation. Left in for experiementation
3908 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3910 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3916 * The function below are the high level ones.
3917 * only those ones must be called from the spoolss code.
3921 /****************************************************************************
3922 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3923 ****************************************************************************/
3925 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3929 dump_a_printer(printer
, level
);
3935 * Update the changestamp. Emperical tests show that the
3936 * ChangeID is always updated,but c_setprinter is
3937 * global spooler variable (not per printer).
3940 /* ChangeID **must** be increasing over the lifetime
3941 of client's spoolss service in order for the
3942 client's cache to show updates */
3944 printer
->info_2
->changeid
= rev_changeid();
3947 * Because one day someone will ask:
3948 * NT->NT An admin connection to a remote
3949 * printer show changes imeediately in
3950 * the properities dialog
3952 * A non-admin connection will only show the
3953 * changes after viewing the properites page
3954 * 2 times. Seems to be related to a
3955 * race condition in the client between the spooler
3956 * updating the local cache and the Explorer.exe GUI
3957 * actually displaying the properties.
3959 * This is fixed in Win2k. admin/non-admin
3960 * connections both display changes immediately.
3965 result
=update_a_printer_2(printer
->info_2
);
3970 result
=WERR_UNKNOWN_LEVEL
;
3977 /****************************************************************************
3978 Initialize printer devmode & data with previously saved driver init values.
3979 ****************************************************************************/
3981 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3985 TDB_DATA kbuf
, dbuf
;
3986 NT_PRINTER_INFO_LEVEL_2 info
;
3992 * Delete any printer data 'values' already set. When called for driver
3993 * replace, there will generally be some, but during an add printer, there
3994 * should not be any (if there are delete them).
3997 if ( info_ptr
->data
)
3998 delete_all_printer_data( info_ptr
, "" );
4000 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
4003 kbuf
.dsize
= strlen(key
)+1;
4005 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
4008 * When changing to a driver that has no init info in the tdb, remove
4009 * the previous drivers init info and leave the new on blank.
4011 free_nt_devicemode(&info_ptr
->devmode
);
4016 * Get the saved DEVMODE..
4019 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4022 * The saved DEVMODE contains the devicename from the printer used during
4023 * the initialization save. Change it to reflect the new printer.
4026 if ( info
.devmode
) {
4027 ZERO_STRUCT(info
.devmode
->devicename
);
4028 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
4032 * NT/2k does not change out the entire DeviceMode of a printer
4033 * when changing the driver. Only the driverextra, private, &
4034 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4036 * Later examination revealed that Windows NT/2k does reset the
4037 * the printer's device mode, bit **only** when you change a
4038 * property of the device mode such as the page orientation.
4043 /* Bind the saved DEVMODE to the new the printer */
4045 free_nt_devicemode(&info_ptr
->devmode
);
4046 info_ptr
->devmode
= info
.devmode
;
4048 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4049 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
4051 /* Add the printer data 'values' to the new printer */
4053 if ( !(info_ptr
->data
= TALLOC_ZERO_P( info_ptr
, NT_PRINTER_DATA
)) ) {
4054 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4058 len
+= unpack_values( info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4061 SAFE_FREE(dbuf
.dptr
);
4066 /****************************************************************************
4067 Initialize printer devmode & data with previously saved driver init values.
4068 When a printer is created using AddPrinter, the drivername bound to the
4069 printer is used to lookup previously saved driver initialization info, which
4070 is bound to the new printer.
4071 ****************************************************************************/
4073 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4075 BOOL result
= False
;
4079 result
= set_driver_init_2(printer
->info_2
);
4083 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4091 /****************************************************************************
4092 Delete driver init data stored for a specified driver
4093 ****************************************************************************/
4095 BOOL
del_driver_init(char *drivername
)
4100 if (!drivername
|| !*drivername
) {
4101 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4105 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
4108 kbuf
.dsize
= strlen(key
)+1;
4110 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
4112 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
4115 /****************************************************************************
4116 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4117 in the tdb. Note: this is different from the driver entry and the printer
4118 entry. There should be a single driver init entry for each driver regardless
4119 of whether it was installed from NT or 2K. Technically, they should be
4120 different, but they work out to the same struct.
4121 ****************************************************************************/
4123 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4127 int buflen
, len
, ret
;
4128 TDB_DATA kbuf
, dbuf
;
4135 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4137 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
4140 buf
= (char *)SMB_REALLOC(buf
, len
);
4142 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4150 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
4153 kbuf
.dsize
= strlen(key
)+1;
4157 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
4161 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4165 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4166 info
->sharename
, info
->drivername
));
4171 /****************************************************************************
4172 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4173 ****************************************************************************/
4175 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4179 dump_a_printer(printer
, level
);
4183 result
= update_driver_init_2(printer
->info_2
);
4193 /****************************************************************************
4194 Convert the printer data value, a REG_BINARY array, into an initialization
4195 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4196 got to keep the endians happy :).
4197 ****************************************************************************/
4199 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
4201 BOOL result
= False
;
4205 ZERO_STRUCT(devmode
);
4207 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
4208 ps
.data_p
= (char *)data
;
4209 ps
.buffer_size
= data_len
;
4211 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
4212 result
= convert_devicemode("", &devmode
, &nt_devmode
);
4214 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4219 /****************************************************************************
4220 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4222 1. Use the driver's config DLL to this UNC printername and:
4223 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4224 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4225 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4227 The last step triggers saving the "driver initialization" information for
4228 this printer into the tdb. Later, new printers that use this driver will
4229 have this initialization information bound to them. This simulates the
4230 driver initialization, as if it had run on the Samba server (as it would
4233 The Win32 client side code requirement sucks! But until we can run arbitrary
4234 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4236 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4237 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4238 about it and you will realize why. JRR 010720
4239 ****************************************************************************/
4241 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4243 WERROR status
= WERR_OK
;
4244 TALLOC_CTX
*ctx
= NULL
;
4245 NT_DEVICEMODE
*nt_devmode
= NULL
;
4246 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4249 * When the DEVMODE is already set on the printer, don't try to unpack it.
4251 DEBUG(8,("save_driver_init_2: Enter...\n"));
4253 if ( !printer
->info_2
->devmode
&& data_len
) {
4255 * Set devmode on printer info, so entire printer initialization can be
4259 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4262 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4263 status
= WERR_NOMEM
;
4267 ZERO_STRUCTP(nt_devmode
);
4270 * The DEVMODE is held in the 'data' component of the param in raw binary.
4271 * Convert it to to a devmode structure
4273 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4274 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4275 status
= WERR_INVALID_PARAM
;
4279 printer
->info_2
->devmode
= nt_devmode
;
4283 * Pack up and add (or update) the DEVMODE and any current printer data to
4284 * a 'driver init' element in the tdb
4288 if ( update_driver_init(printer
, 2) != 0 ) {
4289 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4290 status
= WERR_NOMEM
;
4295 * If driver initialization info was successfully saved, set the current
4296 * printer to match it. This allows initialization of the current printer
4297 * as well as the driver.
4299 status
= mod_a_printer(printer
, 2);
4300 if (!W_ERROR_IS_OK(status
)) {
4301 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4302 printer
->info_2
->printername
));
4306 talloc_destroy(ctx
);
4307 free_nt_devicemode( &nt_devmode
);
4309 printer
->info_2
->devmode
= tmp_devmode
;
4314 /****************************************************************************
4315 Update the driver init info (DEVMODE and specifics) for a printer
4316 ****************************************************************************/
4318 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4320 WERROR status
= WERR_OK
;
4324 status
= save_driver_init_2( printer
, data
, data_len
);
4327 status
= WERR_UNKNOWN_LEVEL
;
4334 /****************************************************************************
4335 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4337 Previously the code had a memory allocation problem because it always
4338 used the TALLOC_CTX from the Printer_entry*. This context lasts
4339 as a long as the original handle is open. So if the client made a lot
4340 of getprinter[data]() calls, the memory usage would climb. Now we use
4341 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4342 still use the Printer_entry->ctx for maintaining the cache copy though
4343 since that object must live as long as the handle by definition.
4346 ****************************************************************************/
4348 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4349 const char *sharename
)
4354 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4356 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4357 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4363 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4364 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4365 TALLOC_FREE( *pp_printer
);
4370 fstrcpy( servername
, print_hnd
->servername
);
4372 fstrcpy( servername
, "%L" );
4373 standard_sub_basic( "", "", servername
,
4374 sizeof(servername
)-1 );
4377 result
= get_a_printer_2( (*pp_printer
)->info_2
, servername
, sharename
);
4380 /* we have a new printer now. Save it with this handle */
4382 if ( !W_ERROR_IS_OK(result
) ) {
4383 TALLOC_FREE( *pp_printer
);
4384 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4385 sharename
, (unsigned int)level
, dos_errstr(result
)));
4389 dump_a_printer( *pp_printer
, level
);
4394 TALLOC_FREE( *pp_printer
);
4395 return WERR_UNKNOWN_LEVEL
;
4401 /****************************************************************************
4402 Deletes a NT_PRINTER_INFO_LEVEL struct.
4403 ****************************************************************************/
4405 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4407 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4414 if ( printer
->info_2
)
4415 free_nt_printer_info_level_2(&printer
->info_2
);
4419 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4423 TALLOC_FREE(*pp_printer
);
4428 /****************************************************************************
4429 ****************************************************************************/
4430 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4433 DEBUG(104,("adding a printer at level [%d]\n", level
));
4434 dump_a_printer_driver(driver
, level
);
4438 result
=add_a_printer_driver_3(driver
.info_3
);
4442 result
=add_a_printer_driver_6(driver
.info_6
);
4452 /****************************************************************************
4453 ****************************************************************************/
4455 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4456 fstring drivername
, const char *architecture
, uint32 version
)
4462 /* Sometime we just want any version of the driver */
4464 if ( version
== DRIVER_ANY_VERSION
) {
4465 /* look for Win2k first and then for NT4 */
4466 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4469 if ( !W_ERROR_IS_OK(result
) ) {
4470 result
= get_a_printer_driver_3( &driver
->info_3
,
4471 drivername
, architecture
, 2 );
4474 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4475 architecture
, version
);
4484 if (W_ERROR_IS_OK(result
))
4485 dump_a_printer_driver(*driver
, level
);
4490 /****************************************************************************
4491 ****************************************************************************/
4492 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4499 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4500 if (driver
.info_3
!= NULL
)
4502 info3
=driver
.info_3
;
4503 SAFE_FREE(info3
->dependentfiles
);
4504 ZERO_STRUCTP(info3
);
4514 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4515 if (driver
.info_6
!= NULL
) {
4516 info6
=driver
.info_6
;
4517 SAFE_FREE(info6
->dependentfiles
);
4518 SAFE_FREE(info6
->previousnames
);
4519 ZERO_STRUCTP(info6
);
4535 /****************************************************************************
4536 Determine whether or not a particular driver is currently assigned
4538 ****************************************************************************/
4540 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4543 int n_services
= lp_numservices();
4544 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4545 BOOL in_use
= False
;
4550 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4552 /* loop through the printers.tdb and check for the drivername */
4554 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4555 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4558 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4561 if ( strequal(info_3
->name
, printer
->info_2
->drivername
) )
4564 free_a_printer( &printer
, 2 );
4567 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4570 NT_PRINTER_DRIVER_INFO_LEVEL d
;
4573 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3
->name
));
4575 /* we can still remove the driver if there is one of
4576 "Windows NT x86" version 2 or 3 left */
4578 if ( !strequal( "Windows NT x86", info_3
->environment
) ) {
4579 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4582 switch ( info_3
->cversion
) {
4584 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 3 );
4587 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 2 );
4590 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4592 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4597 /* now check the error code */
4599 if ( W_ERROR_IS_OK(werr
) ) {
4600 /* it's ok to remove the driver, we have other architctures left */
4602 free_a_printer_driver( d
, 3 );
4606 /* report that the driver is not in use by default */
4612 /**********************************************************************
4613 Check to see if a ogiven file is in use by *info
4614 *********************************************************************/
4616 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4623 if ( strequal(file
, info
->driverpath
) )
4626 if ( strequal(file
, info
->datafile
) )
4629 if ( strequal(file
, info
->configfile
) )
4632 if ( strequal(file
, info
->helpfile
) )
4635 /* see of there are any dependent files to examine */
4637 if ( !info
->dependentfiles
)
4640 while ( *info
->dependentfiles
[i
] ) {
4641 if ( strequal(file
, info
->dependentfiles
[i
]) )
4650 /**********************************************************************
4651 Utility function to remove the dependent file pointed to by the
4652 input parameter from the list
4653 *********************************************************************/
4655 static void trim_dependent_file( fstring files
[], int idx
)
4658 /* bump everything down a slot */
4660 while( *files
[idx
+1] ) {
4661 fstrcpy( files
[idx
], files
[idx
+1] );
4670 /**********************************************************************
4671 Check if any of the files used by src are also used by drv
4672 *********************************************************************/
4674 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4675 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4677 BOOL in_use
= False
;
4683 /* check each file. Remove it from the src structure if it overlaps */
4685 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4687 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4688 fstrcpy( src
->driverpath
, "" );
4691 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4693 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4694 fstrcpy( src
->datafile
, "" );
4697 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4699 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4700 fstrcpy( src
->configfile
, "" );
4703 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4705 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4706 fstrcpy( src
->helpfile
, "" );
4709 /* are there any dependentfiles to examine? */
4711 if ( !src
->dependentfiles
)
4714 while ( *src
->dependentfiles
[i
] ) {
4715 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4717 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4718 trim_dependent_file( src
->dependentfiles
, i
);
4726 /****************************************************************************
4727 Determine whether or not a particular driver files are currently being
4728 used by any other driver.
4730 Return value is True if any files were in use by other drivers
4731 and False otherwise.
4733 Upon return, *info has been modified to only contain the driver files
4734 which are not in use
4735 ****************************************************************************/
4737 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4742 fstring
*list
= NULL
;
4743 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4748 version
= info
->cversion
;
4750 /* loop over all driver versions */
4752 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4754 /* get the list of drivers */
4757 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4759 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4760 ndrivers
, info
->environment
, version
));
4762 /* check each driver for overlap in files */
4764 for (i
=0; i
<ndrivers
; i
++) {
4765 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4767 ZERO_STRUCT(driver
);
4769 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4774 /* check if d2 uses any files from d1 */
4775 /* only if this is a different driver than the one being deleted */
4777 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4778 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4779 free_a_printer_driver(driver
, 3);
4785 free_a_printer_driver(driver
, 3);
4790 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4792 driver
.info_3
= info
;
4794 if ( DEBUGLEVEL
>= 20 )
4795 dump_a_printer_driver( driver
, 3 );
4800 /****************************************************************************
4801 Actually delete the driver files. Make sure that
4802 printer_driver_files_in_use() return False before calling
4804 ****************************************************************************/
4806 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4811 connection_struct
*conn
;
4821 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4824 * Connect to the print$ share under the same account as the
4825 * user connected to the rpc pipe. Note we must be root to
4829 null_pw
= data_blob( NULL
, 0 );
4830 fstrcpy(res_type
, "A:");
4832 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4836 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4840 if ( !CAN_WRITE(conn
) ) {
4841 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4845 /* Save who we are - we are temporarily becoming the connection user. */
4847 if ( !become_user(conn
, conn
->vuid
) ) {
4848 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4852 /* now delete the files; must strip the '\print$' string from
4855 if ( *info_3
->driverpath
) {
4856 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4858 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4859 DEBUG(10,("deleting driverfile [%s]\n", s
));
4860 unlink_internals(conn
, 0, file
, False
);
4864 if ( *info_3
->configfile
) {
4865 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4867 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4868 DEBUG(10,("deleting configfile [%s]\n", s
));
4869 unlink_internals(conn
, 0, file
, False
);
4873 if ( *info_3
->datafile
) {
4874 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4876 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4877 DEBUG(10,("deleting datafile [%s]\n", s
));
4878 unlink_internals(conn
, 0, file
, False
);
4882 if ( *info_3
->helpfile
) {
4883 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4885 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4886 DEBUG(10,("deleting helpfile [%s]\n", s
));
4887 unlink_internals(conn
, 0, file
, False
);
4891 /* check if we are done removing files */
4893 if ( info_3
->dependentfiles
) {
4894 while ( info_3
->dependentfiles
[i
][0] ) {
4897 /* bypass the "\print$" portion of the path */
4899 if ( (p
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4901 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4902 DEBUG(10,("deleting dependent file [%s]\n", file
));
4903 unlink_internals(conn
, 0, file
, False
);
4915 /****************************************************************************
4916 Remove a printer driver from the TDB. This assumes that the the driver was
4917 previously looked up.
4918 ***************************************************************************/
4920 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4921 uint32 version
, BOOL delete_files
)
4925 TDB_DATA kbuf
, dbuf
;
4926 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4928 /* delete the tdb data first */
4930 arch
= get_short_archi(info_3
->environment
);
4932 return WERR_UNKNOWN_PRINTER_DRIVER
;
4934 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4935 arch
, version
, info_3
->name
);
4937 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4938 key
, delete_files
? "TRUE" : "FALSE" ));
4940 ctr
.info_3
= info_3
;
4941 dump_a_printer_driver( ctr
, 3 );
4944 kbuf
.dsize
=strlen(key
)+1;
4946 /* check if the driver actually exists for this environment */
4948 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4950 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4951 return WERR_UNKNOWN_PRINTER_DRIVER
;
4954 SAFE_FREE( dbuf
.dptr
);
4956 /* ok... the driver exists so the delete should return success */
4958 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4959 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4960 return WERR_ACCESS_DENIED
;
4964 * now delete any associated files if delete_files == True
4965 * even if this part failes, we return succes because the
4966 * driver doesn not exist any more
4970 delete_driver_files( info_3
, user
);
4973 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4978 /****************************************************************************
4979 Store a security desc for a printer.
4980 ****************************************************************************/
4982 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
4984 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4985 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4987 TALLOC_CTX
*mem_ctx
= NULL
;
4991 mem_ctx
= talloc_init("nt_printing_setsec");
4992 if (mem_ctx
== NULL
)
4995 /* The old owner and group sids of the security descriptor are not
4996 present when new ACEs are added or removed by changing printer
4997 permissions through NT. If they are NULL in the new security
4998 descriptor then copy them over from the old one. */
5000 if (!secdesc_ctr
->sd
->owner_sid
|| !secdesc_ctr
->sd
->group_sid
) {
5001 DOM_SID
*owner_sid
, *group_sid
;
5002 SEC_ACL
*dacl
, *sacl
;
5003 SEC_DESC
*psd
= NULL
;
5006 if (!nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
)) {
5007 status
= WERR_NOMEM
;
5011 /* Pick out correct owner and group sids */
5013 owner_sid
= secdesc_ctr
->sd
->owner_sid
?
5014 secdesc_ctr
->sd
->owner_sid
:
5015 old_secdesc_ctr
->sd
->owner_sid
;
5017 group_sid
= secdesc_ctr
->sd
->group_sid
?
5018 secdesc_ctr
->sd
->group_sid
:
5019 old_secdesc_ctr
->sd
->group_sid
;
5021 dacl
= secdesc_ctr
->sd
->dacl
?
5022 secdesc_ctr
->sd
->dacl
:
5023 old_secdesc_ctr
->sd
->dacl
;
5025 sacl
= secdesc_ctr
->sd
->sacl
?
5026 secdesc_ctr
->sd
->sacl
:
5027 old_secdesc_ctr
->sd
->sacl
;
5029 /* Make a deep copy of the security descriptor */
5031 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sd
->revision
, secdesc_ctr
->sd
->type
,
5032 owner_sid
, group_sid
,
5038 status
= WERR_NOMEM
;
5042 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
5045 if (!new_secdesc_ctr
) {
5046 new_secdesc_ctr
= secdesc_ctr
;
5049 /* Store the security descriptor in a tdb */
5051 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sd
) +
5052 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
5054 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
5056 status
= WERR_BADFUNC
;
5060 key
= make_printers_secdesc_tdbkey( sharename
);
5062 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
5065 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
5066 status
= WERR_BADFUNC
;
5069 /* Free malloc'ed memory */
5075 talloc_destroy(mem_ctx
);
5079 /****************************************************************************
5080 Construct a default security descriptor buffer for a printer.
5081 ****************************************************************************/
5083 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5085 SEC_ACE ace
[5]; /* max number of ace entries */
5088 SEC_ACL
*psa
= NULL
;
5089 SEC_DESC_BUF
*sdb
= NULL
;
5090 SEC_DESC
*psd
= NULL
;
5094 /* Create an ACE where Everyone is allowed to print */
5096 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
5097 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5098 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5100 /* Add the domain admins group if we are a DC */
5103 DOM_SID domadmins_sid
;
5105 sid_copy(&domadmins_sid
, get_global_sam_sid());
5106 sid_append_rid(&domadmins_sid
, DOMAIN_GROUP_RID_ADMINS
);
5108 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5109 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5110 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5111 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5112 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5113 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5115 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5116 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5118 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5119 init_sec_ace(&ace
[i
++], &adm_sid
,
5120 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5121 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5122 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5123 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5126 /* add BUILTIN\Administrators as FULL CONTROL */
5128 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5129 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5130 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5131 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5132 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5133 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5134 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5136 /* Make the security descriptor owned by the BUILTIN\Administrators */
5138 /* The ACL revision number in rpc_secdesc.h differs from the one
5139 created by NT when setting ACE entries in printer
5140 descriptors. NT4 complains about the property being edited by a
5143 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5144 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5145 &global_sid_Builtin_Administrators
,
5146 &global_sid_Builtin_Administrators
,
5147 NULL
, psa
, &sd_size
);
5151 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5155 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5157 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5158 (unsigned int)sd_size
));
5163 /****************************************************************************
5164 Get a security desc for a printer.
5165 ****************************************************************************/
5167 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5173 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5174 sharename
= temp
+ 1;
5179 /* Fetch security descriptor from tdb */
5181 key
= make_printers_secdesc_tdbkey( sharename
);
5183 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
5184 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5188 DEBUG(4,("using default secdesc for %s\n", sharename
));
5190 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
5194 /* Save default security descriptor for later */
5196 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sd
) +
5197 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
5199 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5200 tdb_prs_store(tdb_printers
, key
, &ps
);
5210 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5211 this security descriptor has been created when winbindd was
5212 down. Take ownership of security descriptor. */
5214 if (sid_equal((*secdesc_ctr
)->sd
->owner_sid
, &global_sid_World
)) {
5217 /* Change sd owner to workgroup administrator */
5219 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5220 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5221 SEC_DESC
*psd
= NULL
;
5226 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5228 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sd
->revision
, (*secdesc_ctr
)->sd
->type
,
5230 (*secdesc_ctr
)->sd
->group_sid
,
5231 (*secdesc_ctr
)->sd
->sacl
,
5232 (*secdesc_ctr
)->sd
->dacl
,
5239 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5240 if (!new_secdesc_ctr
) {
5244 /* Swap with other one */
5246 *secdesc_ctr
= new_secdesc_ctr
;
5250 nt_printing_setsec(sharename
, *secdesc_ctr
);
5254 if (DEBUGLEVEL
>= 10) {
5255 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sd
->dacl
;
5258 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5259 sharename
, the_acl
->num_aces
));
5261 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5264 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5266 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
5267 the_acl
->aces
[i
].type
, the_acl
->aces
[i
].flags
,
5268 the_acl
->aces
[i
].access_mask
));
5277 1: level not implemented
5278 2: file doesn't exist
5279 3: can't allocate memory
5280 4: can't free memory
5281 5: non existant struct
5285 A printer and a printer driver are 2 different things.
5286 NT manages them separatelly, Samba does the same.
5287 Why ? Simply because it's easier and it makes sense !
5289 Now explanation: You have 3 printers behind your samba server,
5290 2 of them are the same make and model (laser A and B). But laser B
5291 has an 3000 sheet feeder and laser A doesn't such an option.
5292 Your third printer is an old dot-matrix model for the accounting :-).
5294 If the /usr/local/samba/lib directory (default dir), you will have
5295 5 files to describe all of this.
5297 3 files for the printers (1 by printer):
5300 NTprinter_accounting
5301 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5302 NTdriver_printer model X
5303 NTdriver_printer model Y
5305 jfm: I should use this comment for the text file to explain
5306 same thing for the forms BTW.
5307 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5311 /* Convert generic access rights to printer object specific access rights.
5312 It turns out that NT4 security descriptors use generic access rights and
5313 NT5 the object specific ones. */
5315 void map_printer_permissions(SEC_DESC
*sd
)
5319 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5320 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5321 &printer_generic_mapping
);
5325 /****************************************************************************
5326 Check a user has permissions to perform the given operation. We use the
5327 permission constants defined in include/rpc_spoolss.h to check the various
5328 actions we perform when checking printer access.
5330 PRINTER_ACCESS_ADMINISTER:
5331 print_queue_pause, print_queue_resume, update_printer_sec,
5332 update_printer, spoolss_addprinterex_level_2,
5333 _spoolss_setprinterdata
5338 JOB_ACCESS_ADMINISTER:
5339 print_job_delete, print_job_pause, print_job_resume,
5342 Try access control in the following order (for performance reasons):
5343 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5344 2) check security descriptor (bit comparisons in memory)
5345 3) "printer admins" (may result in numerous calls to winbind)
5347 ****************************************************************************/
5348 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5350 SEC_DESC_BUF
*secdesc
= NULL
;
5351 uint32 access_granted
;
5355 TALLOC_CTX
*mem_ctx
= NULL
;
5356 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5358 /* If user is NULL then use the current_user structure */
5361 user
= ¤t_user
;
5363 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5365 if ( user
->ut
.uid
== 0 || user_has_privileges(user
->nt_user_token
, &se_printop
) ) {
5369 /* Get printer name */
5371 pname
= PRINTERNAME(snum
);
5373 if (!pname
|| !*pname
) {
5378 /* Get printer security descriptor */
5380 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5385 if (!nt_printing_getsec(mem_ctx
, pname
, &secdesc
)) {
5386 talloc_destroy(mem_ctx
);
5391 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5392 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5394 /* Create a child security descriptor to check permissions
5395 against. This is because print jobs are child objects
5396 objects of a printer. */
5398 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sd
, False
);
5401 talloc_destroy(mem_ctx
);
5406 /* Now this is the bit that really confuses me. The access
5407 type needs to be changed from JOB_ACCESS_ADMINISTER to
5408 PRINTER_ACCESS_ADMINISTER for this to work. Something
5409 to do with the child (job) object becoming like a
5412 access_type
= PRINTER_ACCESS_ADMINISTER
;
5417 map_printer_permissions(secdesc
->sd
);
5419 result
= se_access_check(secdesc
->sd
, user
->nt_user_token
, access_type
,
5420 &access_granted
, &status
);
5422 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5424 /* see if we need to try the printer admin list */
5426 if ((access_granted
== 0) &&
5427 (token_contains_name_in_list(uidtoname(user
->ut
.uid
), NULL
,
5428 user
->nt_user_token
,
5429 lp_printer_admin(snum
)))) {
5430 talloc_destroy(mem_ctx
);
5434 talloc_destroy(mem_ctx
);
5443 /****************************************************************************
5444 Check the time parameters allow a print operation.
5445 *****************************************************************************/
5447 BOOL
print_time_access_check(const char *servicename
)
5449 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5451 time_t now
= time(NULL
);
5455 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
5458 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5462 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5464 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5467 free_a_printer(&printer
, 2);
5475 /****************************************************************************
5476 Fill in the servername sent in the _spoolss_open_printer_ex() call
5477 ****************************************************************************/
5479 char* get_server_name( Printer_entry
*printer
)
5481 return printer
->servername
;