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
;
345 uint32 sd_size
, size_new_sec
;
348 if (!data
.dptr
|| data
.dsize
== 0)
351 if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 )
354 /* upgrade the security descriptor */
358 prs_init( &ps
, 0, ctx
, UNMARSHALL
);
359 prs_give_memory( &ps
, data
.dptr
, data
.dsize
, True
);
361 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig
, &ps
, 1 ) ) {
362 /* delete bad entries */
363 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n", key
.dptr
));
364 tdb_delete( tdb_printers
, key
);
370 /* is this even valid? */
375 /* update access masks */
377 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
378 switch ( sec
->dacl
->ace
[i
].info
.mask
) {
379 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
380 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_PRINT
;
383 case GENERIC_ALL_ACCESS
:
384 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_FULL_CONTROL
;
387 case READ_CONTROL_ACCESS
:
388 sec
->dacl
->ace
[i
].info
.mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
390 default: /* no change */
395 /* create a new SEC_DESC with the appropriate owner and group SIDs */
397 string_to_sid(&sid
, "S-1-5-32-544" );
398 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
400 NULL
, NULL
, &size_new_sec
);
401 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
403 if ( !(sd_store
= sec_desc_merge( ctx
, sd_new
, sd_orig
)) ) {
404 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
410 sd_size
= sec_desc_size(sd_store
->sec
) + sizeof(SEC_DESC_BUF
);
411 prs_init(&ps
, sd_size
, ctx
, MARSHALL
);
413 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store
, &ps
, 1 ) ) {
414 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
418 data
.dptr
= prs_data_p( &ps
);
419 data
.dsize
= sd_size
;
421 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
425 /* 0 to continue and non-zero to stop traversal */
427 return (result
== -1);
430 /*******************************************************************
431 *******************************************************************/
433 static BOOL
upgrade_to_version_4(void)
438 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
440 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
443 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
445 talloc_destroy( ctx
);
447 return ( result
!= -1 );
450 /*******************************************************************
451 Fix an issue with security descriptors. Printer sec_desc must
452 use more than the generic bits that were previously used
453 in <= 3.0.14a. They must also have a owner and group SID assigned.
454 Otherwise, any printers than have been migrated to a Windows
455 host using printmig.exe will not be accessible.
456 *******************************************************************/
458 static int normalize_printers_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
459 TDB_DATA data
, void *state
)
463 if (!data
.dptr
|| data
.dsize
== 0)
466 /* upgrade printer records and security descriptors */
468 if ( strncmp( key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
469 new_key
= make_printer_tdbkey( key
.dptr
+strlen(PRINTERS_PREFIX
) );
471 else if ( strncmp( key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
472 new_key
.dptr
= make_printers_secdesc_tdbkey( key
.dptr
+strlen(SECDESC_PREFIX
) );
473 new_key
.dsize
= strlen( new_key
.dptr
) + 1;
476 /* ignore this record */
480 /* delete the original record and store under the normalized key */
482 if ( tdb_delete( the_tdb
, key
) != 0 ) {
483 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
488 if ( tdb_store( the_tdb
, new_key
, data
, TDB_REPLACE
) != 0 ) {
489 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
497 /*******************************************************************
498 *******************************************************************/
500 static BOOL
upgrade_to_version_5(void)
505 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
507 if ( !(ctx
= talloc_init( "upgrade_to_version_5" )) )
510 result
= tdb_traverse( tdb_printers
, normalize_printers_fn
, NULL
);
512 talloc_destroy( ctx
);
514 return ( result
!= -1 );
517 /****************************************************************************
518 Open the NT printing tdbs. Done once before fork().
519 ****************************************************************************/
521 BOOL
nt_printing_init(void)
523 const char *vstring
= "INFO/version";
527 if ( tdb_drivers
&& tdb_printers
&& tdb_forms
)
531 tdb_close(tdb_drivers
);
532 tdb_drivers
= tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
534 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
535 lock_path("ntdrivers.tdb"), strerror(errno
) ));
540 tdb_close(tdb_printers
);
541 tdb_printers
= tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
543 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
544 lock_path("ntprinters.tdb"), strerror(errno
) ));
549 tdb_close(tdb_forms
);
550 tdb_forms
= tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
552 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
553 lock_path("ntforms.tdb"), strerror(errno
) ));
557 /* handle a Samba upgrade */
559 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
561 DEBUG(10, ("Fresh database\n"));
562 tdb_store_int32( tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
563 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
566 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
568 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
569 if (!upgrade_to_version_3())
571 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
572 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
575 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
576 /* Written on a bigendian machine with old fetch_int code. Save as le. */
577 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
578 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
579 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
582 if (vers_id
== NTDRIVERS_DATABASE_VERSION_3
) {
583 if ( !upgrade_to_version_4() )
585 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_4
);
586 vers_id
= NTDRIVERS_DATABASE_VERSION_4
;
589 if (vers_id
== NTDRIVERS_DATABASE_VERSION_4
) {
590 if ( !upgrade_to_version_5() )
592 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
593 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
597 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
598 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id
));
603 update_c_setprinter(True
);
606 * register callback to handle updating printers as new
607 * drivers are installed
610 message_register( MSG_PRINTER_DRVUPGRADE
, do_drv_upgrade_printer
);
613 * register callback to handle updating printer data
614 * when a driver is initialized
617 message_register( MSG_PRINTERDATA_INIT_RESET
, reset_all_printerdata
);
619 /* of course, none of the message callbacks matter if you don't
620 tell messages.c that you interested in receiving PRINT_GENERAL
621 msgs. This is done in claim_connection() */
624 if ( lp_security() == SEC_ADS
) {
625 win_rc
= check_published_printers();
626 if (!W_ERROR_IS_OK(win_rc
))
627 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc
)));
633 /*******************************************************************
634 Function to allow filename parsing "the old way".
635 ********************************************************************/
637 static BOOL
driver_unix_convert(char *name
,connection_struct
*conn
,
638 char *saved_last_component
, BOOL
*bad_path
, SMB_STRUCT_STAT
*pst
)
641 unix_clean_name(name
);
642 trim_string(name
,"/","/");
643 return unix_convert(name
, conn
, saved_last_component
, bad_path
, pst
);
646 /*******************************************************************
647 tdb traversal function for counting printers.
648 ********************************************************************/
650 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
651 TDB_DATA data
, void *context
)
653 int *printer_count
= (int*)context
;
655 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
657 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
663 /*******************************************************************
664 Update the spooler global c_setprinter. This variable is initialized
665 when the parent smbd starts with the number of existing printers. It
666 is monotonically increased by the current number of printers *after*
667 each add or delete printer RPC. Only Microsoft knows why... JRR020119
668 ********************************************************************/
670 uint32
update_c_setprinter(BOOL initialize
)
673 int32 printer_count
= 0;
675 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
, 0);
677 /* Traverse the tdb, counting the printers */
678 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
680 /* If initializing, set c_setprinter to current printers count
681 * otherwise, bump it by the current printer count
684 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
686 c_setprinter
= printer_count
;
688 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
689 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
691 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
693 return (uint32
)c_setprinter
;
696 /*******************************************************************
697 Get the spooler global c_setprinter, accounting for initialization.
698 ********************************************************************/
700 uint32
get_c_setprinter(void)
702 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
704 if (c_setprinter
== (int32
)-1)
705 c_setprinter
= update_c_setprinter(True
);
707 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
709 return (uint32
)c_setprinter
;
712 /****************************************************************************
713 Get builtin form struct list.
714 ****************************************************************************/
716 int get_builtin_ntforms(nt_forms_struct
**list
)
718 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
719 return sizeof(default_forms
) / sizeof(default_forms
[0]);
722 /****************************************************************************
723 get a builtin form struct
724 ****************************************************************************/
726 BOOL
get_a_builtin_ntform(UNISTR2
*uni_formname
,nt_forms_struct
*form
)
730 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
731 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
732 count
= sizeof(default_forms
) / sizeof(default_forms
[0]);
733 for (i
=0;i
<count
;i
++) {
734 if (strequal(form_name
,default_forms
[i
].name
)) {
735 DEBUGADD(6,("Found builtin form %s \n", form_name
));
736 memcpy(form
,&default_forms
[i
],sizeof(*form
));
744 /****************************************************************************
745 get a form struct list
746 ****************************************************************************/
747 int get_ntforms(nt_forms_struct
**list
)
749 TDB_DATA kbuf
, newkey
, dbuf
;
751 nt_forms_struct form
;
756 for (kbuf
= tdb_firstkey(tdb_forms
);
758 newkey
= tdb_nextkey(tdb_forms
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
)
760 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
763 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
767 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
768 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
769 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
770 &form
.top
, &form
.right
, &form
.bottom
);
771 SAFE_FREE(dbuf
.dptr
);
772 if (ret
!= dbuf
.dsize
)
775 tl
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
777 DEBUG(0,("get_ntforms: Realloc fail.\n"));
789 /****************************************************************************
790 write a form struct list
791 ****************************************************************************/
792 int write_ntforms(nt_forms_struct
**list
, int number
)
799 for (i
=0;i
<number
;i
++) {
800 /* save index, so list is rebuilt in correct order */
801 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
802 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
803 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
805 if (len
> sizeof(buf
)) break;
806 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
807 kbuf
.dsize
= strlen(key
)+1;
811 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
817 /****************************************************************************
818 add a form struct at the end of the list
819 ****************************************************************************/
820 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
828 * NT tries to add forms even when
829 * they are already in the base
830 * only update the values if already present
835 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
836 for (n
=0; n
<*count
; n
++) {
837 if ( strequal((*list
)[n
].name
, form_name
) ) {
844 if((tl
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
845 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
849 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
853 (*list
)[n
].flag
=form
->flags
;
854 (*list
)[n
].width
=form
->size_x
;
855 (*list
)[n
].length
=form
->size_y
;
856 (*list
)[n
].left
=form
->left
;
857 (*list
)[n
].top
=form
->top
;
858 (*list
)[n
].right
=form
->right
;
859 (*list
)[n
].bottom
=form
->bottom
;
861 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
862 update
? "updated" : "added", form_name
));
867 /****************************************************************************
868 Delete a named form struct.
869 ****************************************************************************/
871 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, WERROR
*ret
)
880 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
882 for (n
=0; n
<*count
; n
++) {
883 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
884 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
890 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
891 *ret
= WERR_INVALID_PARAM
;
895 slprintf(key
, sizeof(key
)-1, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
896 kbuf
.dsize
= strlen(key
)+1;
898 if (tdb_delete(tdb_forms
, kbuf
) != 0) {
906 /****************************************************************************
907 Update a form struct.
908 ****************************************************************************/
910 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
914 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
916 DEBUG(106, ("[%s]\n", form_name
));
917 for (n
=0; n
<count
; n
++) {
918 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
919 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
923 if (n
==count
) return;
925 (*list
)[n
].flag
=form
->flags
;
926 (*list
)[n
].width
=form
->size_x
;
927 (*list
)[n
].length
=form
->size_y
;
928 (*list
)[n
].left
=form
->left
;
929 (*list
)[n
].top
=form
->top
;
930 (*list
)[n
].right
=form
->right
;
931 (*list
)[n
].bottom
=form
->bottom
;
934 /****************************************************************************
935 Get the nt drivers list.
936 Traverse the database and look-up the matching names.
937 ****************************************************************************/
938 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
941 const char *short_archi
;
944 TDB_DATA kbuf
, newkey
;
946 short_archi
= get_short_archi(architecture
);
947 slprintf(key
, sizeof(key
)-1, "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
949 for (kbuf
= tdb_firstkey(tdb_drivers
);
951 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
953 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0)
956 if((fl
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
957 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
962 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
969 /****************************************************************************
970 function to do the mapping between the long architecture name and
972 ****************************************************************************/
973 const char *get_short_archi(const char *long_archi
)
977 DEBUG(107,("Getting architecture dependant directory\n"));
980 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
981 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
983 if (archi_table
[i
].long_archi
==NULL
) {
984 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
988 /* this might be client code - but shouldn't this be an fstrcpy etc? */
991 DEBUGADD(108,("index: [%d]\n", i
));
992 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
993 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
995 return archi_table
[i
].short_archi
;
998 /****************************************************************************
999 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1000 There are two case to be covered here: PE (Portable Executable) and NE (New
1001 Executable) files. Both files support the same INFO structure, but PE files
1002 store the signature in unicode, and NE files store it as !unicode.
1003 returns -1 on error, 1 on version info found, and 0 on no version info found.
1004 ****************************************************************************/
1006 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1012 if ((buf
=SMB_MALLOC(PE_HEADER_SIZE
)) == NULL
) {
1013 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
1014 fname
, PE_HEADER_SIZE
));
1018 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
1019 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1020 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1021 fname
, (unsigned long)byte_count
));
1022 goto no_version_info
;
1025 /* Is this really a DOS header? */
1026 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1027 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1028 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1029 goto no_version_info
;
1032 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1033 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1034 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1036 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1037 goto no_version_info
;
1040 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
1041 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1042 fname
, (unsigned long)byte_count
));
1043 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1044 goto no_version_info
;
1047 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1048 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1049 unsigned int num_sections
;
1050 unsigned int section_table_bytes
;
1052 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) != PE_HEADER_MACHINE_I386
) {
1053 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
1054 fname
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
1055 /* At this point, we assume the file is in error. It still could be somthing
1056 * else besides a PE file, but it unlikely at this point.
1061 /* get the section table */
1062 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1063 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1064 if (section_table_bytes
== 0)
1068 if ((buf
=SMB_MALLOC(section_table_bytes
)) == NULL
) {
1069 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1070 fname
, section_table_bytes
));
1074 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1075 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1076 fname
, (unsigned long)byte_count
));
1080 /* Iterate the section table looking for the resource section ".rsrc" */
1081 for (i
= 0; i
< num_sections
; i
++) {
1082 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1084 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1085 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1086 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1088 if (section_bytes
== 0)
1092 if ((buf
=SMB_MALLOC(section_bytes
)) == NULL
) {
1093 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1094 fname
, section_bytes
));
1098 /* Seek to the start of the .rsrc section info */
1099 if (SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1100 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1105 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1106 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1107 fname
, (unsigned long)byte_count
));
1111 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1114 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1115 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1116 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1117 /* Align to next long address */
1118 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1120 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1121 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1122 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1124 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1125 fname
, *major
, *minor
,
1126 (*major
>>16)&0xffff, *major
&0xffff,
1127 (*minor
>>16)&0xffff, *minor
&0xffff));
1136 /* Version info not found, fall back to origin date/time */
1137 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1141 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1142 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1143 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1144 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1145 /* At this point, we assume the file is in error. It still could be somthing
1146 * else besides a NE file, but it unlikely at this point. */
1150 /* Allocate a bit more space to speed up things */
1152 if ((buf
=SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1153 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1154 fname
, PE_HEADER_SIZE
));
1158 /* This is a HACK! I got tired of trying to sort through the messy
1159 * 'NE' file format. If anyone wants to clean this up please have at
1160 * it, but this works. 'NE' files will eventually fade away. JRR */
1161 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1162 /* Cover case that should not occur in a well formed 'NE' .dll file */
1163 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1165 for(i
=0; i
<byte_count
; i
++) {
1166 /* Fast skip past data that can't possibly match */
1167 if (buf
[i
] != 'V') continue;
1169 /* Potential match data crosses buf boundry, move it to beginning
1170 * of buf, and fill the buf with as much as it will hold. */
1171 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1174 memcpy(buf
, &buf
[i
], byte_count
-i
);
1175 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1176 (byte_count
-i
))) < 0) {
1178 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1183 byte_count
= bc
+ (byte_count
- i
);
1184 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1189 /* Check that the full signature string and the magic number that
1190 * follows exist (not a perfect solution, but the chances that this
1191 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1192 * twice, as it is simpler to read the code. */
1193 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1194 /* Compute skip alignment to next long address */
1195 int skip
= -(SMB_VFS_LSEEK(fsp
, fsp
->fh
->fd
, 0, SEEK_CUR
) - (byte_count
- i
) +
1196 sizeof(VS_SIGNATURE
)) & 3;
1197 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1199 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1200 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1201 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1202 fname
, *major
, *minor
,
1203 (*major
>>16)&0xffff, *major
&0xffff,
1204 (*minor
>>16)&0xffff, *minor
&0xffff));
1211 /* Version info not found, fall back to origin date/time */
1212 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1217 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1218 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1219 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1230 /****************************************************************************
1231 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1232 share one or more files. During the MS installation process files are checked
1233 to insure that only a newer version of a shared file is installed over an
1234 older version. There are several possibilities for this comparison. If there
1235 is no previous version, the new one is newer (obviously). If either file is
1236 missing the version info structure, compare the creation date (on Unix use
1237 the modification date). Otherwise chose the numerically larger version number.
1238 ****************************************************************************/
1240 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1242 BOOL use_version
= True
;
1247 time_t new_create_time
;
1251 time_t old_create_time
;
1253 files_struct
*fsp
= NULL
;
1255 SMB_STRUCT_STAT stat_buf
;
1258 SET_STAT_INVALID(st
);
1259 SET_STAT_INVALID(stat_buf
);
1260 new_create_time
= (time_t)0;
1261 old_create_time
= (time_t)0;
1263 /* Get file version info (if available) for previous file (if it exists) */
1264 pstrcpy(filepath
, old_file
);
1266 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1268 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1270 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1273 FILE_ATTRIBUTE_NORMAL
,
1278 /* Old file not found, so by definition new file is in fact newer */
1279 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1284 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1290 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1292 use_version
= False
;
1293 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1294 old_create_time
= st
.st_mtime
;
1295 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time
));
1298 close_file(fsp
, True
);
1300 /* Get file version info (if available) for new file */
1301 pstrcpy(filepath
, new_file
);
1302 driver_unix_convert(filepath
,conn
,NULL
,&bad_path
,&stat_buf
);
1304 fsp
= open_file_ntcreate(conn
, filepath
, &stat_buf
,
1306 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1309 FILE_ATTRIBUTE_NORMAL
,
1314 /* New file not found, this shouldn't occur if the caller did its job */
1315 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1320 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1326 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1328 use_version
= False
;
1329 if (SMB_VFS_FSTAT(fsp
, fsp
->fh
->fd
, &st
) == -1) goto error_exit
;
1330 new_create_time
= st
.st_mtime
;
1331 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time
));
1334 close_file(fsp
, True
);
1336 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1337 /* Compare versions and choose the larger version number */
1338 if (new_major
> old_major
||
1339 (new_major
== old_major
&& new_minor
> old_minor
)) {
1341 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1345 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1350 /* Compare modification time/dates and choose the newest time/date */
1351 if (new_create_time
> old_create_time
) {
1352 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1356 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1363 close_file(fsp
, True
);
1367 /****************************************************************************
1368 Determine the correct cVersion associated with an architecture and driver
1369 ****************************************************************************/
1370 static uint32
get_correct_cversion(const char *architecture
, fstring driverpath_in
,
1371 struct current_user
*user
, WERROR
*perr
)
1378 files_struct
*fsp
= NULL
;
1381 connection_struct
*conn
;
1383 SET_STAT_INVALID(st
);
1385 *perr
= WERR_INVALID_PARAM
;
1387 /* If architecture is Windows 95/98/ME, the version is always 0. */
1388 if (strcmp(architecture
, "WIN40") == 0) {
1389 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1395 * Connect to the print$ share under the same account as the user connected
1396 * to the rpc pipe. Note we must still be root to do this.
1399 /* Null password is ok - we are already an authenticated user... */
1400 null_pw
= data_blob(NULL
, 0);
1401 fstrcpy(res_type
, "A:");
1403 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1407 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1408 *perr
= ntstatus_to_werror(nt_status
);
1412 /* We are temporarily becoming the connection user. */
1413 if (!become_user(conn
, user
->vuid
)) {
1414 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1415 *perr
= WERR_ACCESS_DENIED
;
1419 /* Open the driver file (Portable Executable format) and determine the
1420 * deriver the cversion. */
1421 slprintf(driverpath
, sizeof(driverpath
)-1, "%s/%s", architecture
, driverpath_in
);
1423 driver_unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
1425 if ( !vfs_file_exist( conn
, driverpath
, &st
) ) {
1426 *perr
= WERR_BADFILE
;
1430 fsp
= open_file_ntcreate(conn
, driverpath
, &st
,
1432 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1435 FILE_ATTRIBUTE_NORMAL
,
1440 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1441 driverpath
, errno
));
1442 *perr
= WERR_ACCESS_DENIED
;
1447 int ret
= get_file_version(fsp
, driverpath
, &major
, &minor
);
1448 if (ret
== -1) goto error_exit
;
1451 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath
));
1456 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1457 * for more details. Version in this case is not just the version of the
1458 * file, but the version in the sense of kernal mode (2) vs. user mode
1459 * (3) drivers. Other bits of the version fields are the version info.
1462 cversion
= major
& 0x0000ffff;
1464 case 2: /* WinNT drivers */
1465 case 3: /* Win2K drivers */
1469 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1470 driverpath
, cversion
));
1474 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1475 driverpath
, major
, minor
));
1478 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1479 driverpath
, cversion
));
1481 close_file(fsp
, True
);
1482 close_cnum(conn
, user
->vuid
);
1491 close_file(fsp
, True
);
1493 close_cnum(conn
, user
->vuid
);
1498 /****************************************************************************
1499 ****************************************************************************/
1500 static WERROR
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
1501 struct current_user
*user
)
1503 const char *architecture
;
1509 /* clean up the driver name.
1510 * we can get .\driver.dll
1511 * or worse c:\windows\system\driver.dll !
1513 /* using an intermediate string to not have overlaping memcpy()'s */
1514 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1515 fstrcpy(new_name
, p
+1);
1516 fstrcpy(driver
->driverpath
, new_name
);
1519 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1520 fstrcpy(new_name
, p
+1);
1521 fstrcpy(driver
->datafile
, new_name
);
1524 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1525 fstrcpy(new_name
, p
+1);
1526 fstrcpy(driver
->configfile
, new_name
);
1529 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1530 fstrcpy(new_name
, p
+1);
1531 fstrcpy(driver
->helpfile
, new_name
);
1534 if (driver
->dependentfiles
) {
1535 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1536 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1537 fstrcpy(new_name
, p
+1);
1538 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1543 architecture
= get_short_archi(driver
->environment
);
1545 /* jfm:7/16/2000 the client always sends the cversion=0.
1546 * The server should check which version the driver is by reading
1547 * the PE header of driver->driverpath.
1549 * For Windows 95/98 the version is 0 (so the value sent is correct)
1550 * For Windows NT (the architecture doesn't matter)
1551 * NT 3.1: cversion=0
1552 * NT 3.5/3.51: cversion=1
1556 if ((driver
->cversion
= get_correct_cversion( architecture
, driver
->driverpath
, user
, &err
)) == -1)
1562 /****************************************************************************
1563 ****************************************************************************/
1564 static WERROR
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
, struct current_user
*user
)
1566 const char *architecture
;
1572 /* clean up the driver name.
1573 * we can get .\driver.dll
1574 * or worse c:\windows\system\driver.dll !
1576 /* using an intermediate string to not have overlaping memcpy()'s */
1577 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
1578 fstrcpy(new_name
, p
+1);
1579 fstrcpy(driver
->driverpath
, new_name
);
1582 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
1583 fstrcpy(new_name
, p
+1);
1584 fstrcpy(driver
->datafile
, new_name
);
1587 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
1588 fstrcpy(new_name
, p
+1);
1589 fstrcpy(driver
->configfile
, new_name
);
1592 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
1593 fstrcpy(new_name
, p
+1);
1594 fstrcpy(driver
->helpfile
, new_name
);
1597 if (driver
->dependentfiles
) {
1598 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1599 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
1600 fstrcpy(new_name
, p
+1);
1601 fstrcpy(driver
->dependentfiles
[i
], new_name
);
1606 architecture
= get_short_archi(driver
->environment
);
1608 /* jfm:7/16/2000 the client always sends the cversion=0.
1609 * The server should check which version the driver is by reading
1610 * the PE header of driver->driverpath.
1612 * For Windows 95/98 the version is 0 (so the value sent is correct)
1613 * For Windows NT (the architecture doesn't matter)
1614 * NT 3.1: cversion=0
1615 * NT 3.5/3.51: cversion=1
1620 if ((driver
->version
= get_correct_cversion(architecture
, driver
->driverpath
, user
, &err
)) == -1)
1626 /****************************************************************************
1627 ****************************************************************************/
1628 WERROR
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
1629 uint32 level
, struct current_user
*user
)
1634 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1635 driver
=driver_abstract
.info_3
;
1636 return clean_up_driver_struct_level_3(driver
, user
);
1640 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
1641 driver
=driver_abstract
.info_6
;
1642 return clean_up_driver_struct_level_6(driver
, user
);
1645 return WERR_INVALID_PARAM
;
1649 /****************************************************************************
1650 This function sucks and should be replaced. JRA.
1651 ****************************************************************************/
1653 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*dst
, NT_PRINTER_DRIVER_INFO_LEVEL_6
*src
)
1655 dst
->cversion
= src
->version
;
1657 fstrcpy( dst
->name
, src
->name
);
1658 fstrcpy( dst
->environment
, src
->environment
);
1659 fstrcpy( dst
->driverpath
, src
->driverpath
);
1660 fstrcpy( dst
->datafile
, src
->datafile
);
1661 fstrcpy( dst
->configfile
, src
->configfile
);
1662 fstrcpy( dst
->helpfile
, src
->helpfile
);
1663 fstrcpy( dst
->monitorname
, src
->monitorname
);
1664 fstrcpy( dst
->defaultdatatype
, src
->defaultdatatype
);
1665 dst
->dependentfiles
= src
->dependentfiles
;
1668 #if 0 /* Debugging function */
1670 static char* ffmt(unsigned char *c
){
1672 static char ffmt_str
[17];
1674 for (i
=0; i
<16; i
++) {
1675 if ((c
[i
] < ' ') || (c
[i
] > '~'))
1686 /****************************************************************************
1687 ****************************************************************************/
1688 WERROR
move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
, uint32 level
,
1689 struct current_user
*user
, WERROR
*perr
)
1691 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
1692 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver
;
1693 const char *architecture
;
1698 connection_struct
*conn
;
1709 memset(inbuf
, '\0', sizeof(inbuf
));
1710 memset(outbuf
, '\0', sizeof(outbuf
));
1714 driver
=driver_abstract
.info_3
;
1715 else if (level
==6) {
1716 convert_level_6_to_level3(&converted_driver
, driver_abstract
.info_6
);
1717 driver
= &converted_driver
;
1719 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1720 return WERR_UNKNOWN_LEVEL
;
1723 architecture
= get_short_archi(driver
->environment
);
1726 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1727 * Note we must be root to do this.
1730 null_pw
= data_blob(NULL
, 0);
1731 fstrcpy(res_type
, "A:");
1733 conn
= make_connection_with_chdir("print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
1737 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1738 *perr
= ntstatus_to_werror(nt_status
);
1739 return WERR_NO_SUCH_SHARE
;
1743 * Save who we are - we are temporarily becoming the connection user.
1746 if (!become_user(conn
, conn
->vuid
)) {
1747 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1748 return WERR_ACCESS_DENIED
;
1752 * make the directories version and version\driver_name
1753 * under the architecture directory.
1755 DEBUG(5,("Creating first directory\n"));
1756 slprintf(new_dir
, sizeof(new_dir
)-1, "%s/%d", architecture
, driver
->cversion
);
1757 driver_unix_convert(new_dir
, conn
, NULL
, &bad_path
, &st
);
1758 mkdir_internal(conn
, new_dir
, bad_path
);
1760 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1761 * listed for this driver which has already been moved, skip it (note:
1762 * drivers may list the same file name several times. Then check if the
1763 * file already exists in archi\cversion\, if so, check that the version
1764 * info (or time stamps if version info is unavailable) is newer (or the
1765 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1766 * Otherwise, delete the file.
1768 * If a file is not moved to archi\cversion\ because of an error, all the
1769 * rest of the 'unmoved' driver files are removed from archi\. If one or
1770 * more of the driver's files was already moved to archi\cversion\, it
1771 * potentially leaves the driver in a partially updated state. Version
1772 * trauma will most likely occur if an client attempts to use any printer
1773 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1774 * done is appropriate... later JRR
1777 DEBUG(5,("Moving files now !\n"));
1779 if (driver
->driverpath
&& strlen(driver
->driverpath
)) {
1780 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->driverpath
);
1781 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->driverpath
);
1782 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1783 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1784 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1785 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1786 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1787 new_name
, old_name
));
1788 *perr
= WERR_ACCESS_DENIED
;
1794 if (driver
->datafile
&& strlen(driver
->datafile
)) {
1795 if (!strequal(driver
->datafile
, driver
->driverpath
)) {
1796 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->datafile
);
1797 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->datafile
);
1798 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1799 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1800 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1801 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1802 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1803 new_name
, old_name
));
1804 *perr
= WERR_ACCESS_DENIED
;
1811 if (driver
->configfile
&& strlen(driver
->configfile
)) {
1812 if (!strequal(driver
->configfile
, driver
->driverpath
) &&
1813 !strequal(driver
->configfile
, driver
->datafile
)) {
1814 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->configfile
);
1815 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->configfile
);
1816 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1817 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1818 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1819 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1820 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1821 new_name
, old_name
));
1822 *perr
= WERR_ACCESS_DENIED
;
1829 if (driver
->helpfile
&& strlen(driver
->helpfile
)) {
1830 if (!strequal(driver
->helpfile
, driver
->driverpath
) &&
1831 !strequal(driver
->helpfile
, driver
->datafile
) &&
1832 !strequal(driver
->helpfile
, driver
->configfile
)) {
1833 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->helpfile
);
1834 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->helpfile
);
1835 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1836 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1837 if ( !copy_file(new_name
, old_name
, conn
, OPENX_FILE_EXISTS_TRUNCATE
|
1838 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1839 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1840 new_name
, old_name
));
1841 *perr
= WERR_ACCESS_DENIED
;
1848 if (driver
->dependentfiles
) {
1849 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1850 if (!strequal(driver
->dependentfiles
[i
], driver
->driverpath
) &&
1851 !strequal(driver
->dependentfiles
[i
], driver
->datafile
) &&
1852 !strequal(driver
->dependentfiles
[i
], driver
->configfile
) &&
1853 !strequal(driver
->dependentfiles
[i
], driver
->helpfile
)) {
1855 for (j
=0; j
< i
; j
++) {
1856 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
1861 slprintf(new_name
, sizeof(new_name
)-1, "%s/%s", architecture
, driver
->dependentfiles
[i
]);
1862 slprintf(old_name
, sizeof(old_name
)-1, "%s/%s", new_dir
, driver
->dependentfiles
[i
]);
1863 if (ver
!= -1 && (ver
=file_version_is_newer(conn
, new_name
, old_name
)) > 0) {
1864 driver_unix_convert(new_name
, conn
, NULL
, &bad_path
, &st
);
1865 if ( !copy_file(new_name
, old_name
, conn
,
1866 OPENX_FILE_EXISTS_TRUNCATE
|
1867 OPENX_FILE_CREATE_IF_NOT_EXIST
, 0, False
, &err
) ) {
1868 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1869 new_name
, old_name
));
1870 *perr
= WERR_ACCESS_DENIED
;
1879 close_cnum(conn
, user
->vuid
);
1882 return ver
!= -1 ? WERR_OK
: WERR_UNKNOWN_PRINTER_DRIVER
;
1885 /****************************************************************************
1886 ****************************************************************************/
1887 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1890 const char *architecture
;
1896 TDB_DATA kbuf
, dbuf
;
1898 architecture
= get_short_archi(driver
->environment
);
1900 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1901 * \\server is added in the rpc server layer.
1902 * It does make sense to NOT store the server's name in the printer TDB.
1905 slprintf(directory
, sizeof(directory
)-1, "\\print$\\%s\\%d\\", architecture
, driver
->cversion
);
1907 /* .inf files do not always list a file for each of the four standard files.
1908 * Don't prepend a path to a null filename, or client claims:
1909 * "The server on which the printer resides does not have a suitable
1910 * <printer driver name> printer driver installed. Click OK if you
1911 * wish to install the driver on your local machine."
1913 if (strlen(driver
->driverpath
)) {
1914 fstrcpy(temp_name
, driver
->driverpath
);
1915 slprintf(driver
->driverpath
, sizeof(driver
->driverpath
)-1, "%s%s", directory
, temp_name
);
1918 if (strlen(driver
->datafile
)) {
1919 fstrcpy(temp_name
, driver
->datafile
);
1920 slprintf(driver
->datafile
, sizeof(driver
->datafile
)-1, "%s%s", directory
, temp_name
);
1923 if (strlen(driver
->configfile
)) {
1924 fstrcpy(temp_name
, driver
->configfile
);
1925 slprintf(driver
->configfile
, sizeof(driver
->configfile
)-1, "%s%s", directory
, temp_name
);
1928 if (strlen(driver
->helpfile
)) {
1929 fstrcpy(temp_name
, driver
->helpfile
);
1930 slprintf(driver
->helpfile
, sizeof(driver
->helpfile
)-1, "%s%s", directory
, temp_name
);
1933 if (driver
->dependentfiles
) {
1934 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1935 fstrcpy(temp_name
, driver
->dependentfiles
[i
]);
1936 slprintf(driver
->dependentfiles
[i
], sizeof(driver
->dependentfiles
[i
])-1, "%s%s", directory
, temp_name
);
1940 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, driver
->cversion
, driver
->name
);
1942 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
1949 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1952 driver
->environment
,
1957 driver
->monitorname
,
1958 driver
->defaultdatatype
);
1960 if (driver
->dependentfiles
) {
1961 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
1962 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
1963 driver
->dependentfiles
[i
]);
1967 if (len
!= buflen
) {
1970 tb
= (char *)SMB_REALLOC(buf
, len
);
1972 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1983 kbuf
.dsize
= strlen(key
)+1;
1987 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
1991 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
1997 /****************************************************************************
1998 ****************************************************************************/
1999 static uint32
add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
)
2001 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3
;
2004 info3
.cversion
= driver
->version
;
2005 fstrcpy(info3
.name
,driver
->name
);
2006 fstrcpy(info3
.environment
,driver
->environment
);
2007 fstrcpy(info3
.driverpath
,driver
->driverpath
);
2008 fstrcpy(info3
.datafile
,driver
->datafile
);
2009 fstrcpy(info3
.configfile
,driver
->configfile
);
2010 fstrcpy(info3
.helpfile
,driver
->helpfile
);
2011 fstrcpy(info3
.monitorname
,driver
->monitorname
);
2012 fstrcpy(info3
.defaultdatatype
,driver
->defaultdatatype
);
2013 info3
.dependentfiles
= driver
->dependentfiles
;
2015 return add_a_printer_driver_3(&info3
);
2019 /****************************************************************************
2020 ****************************************************************************/
2021 static WERROR
get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, const char *driver
, const char *arch
)
2023 NT_PRINTER_DRIVER_INFO_LEVEL_3 info
;
2027 fstrcpy(info
.name
, driver
);
2028 fstrcpy(info
.defaultdatatype
, "RAW");
2030 fstrcpy(info
.driverpath
, "");
2031 fstrcpy(info
.datafile
, "");
2032 fstrcpy(info
.configfile
, "");
2033 fstrcpy(info
.helpfile
, "");
2035 if ((info
.dependentfiles
= SMB_MALLOC_ARRAY(fstring
, 2)) == NULL
)
2038 memset(info
.dependentfiles
, '\0', 2*sizeof(fstring
));
2039 fstrcpy(info
.dependentfiles
[0], "");
2041 *info_ptr
= memdup(&info
, sizeof(info
));
2046 /****************************************************************************
2047 ****************************************************************************/
2048 static WERROR
get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
**info_ptr
, fstring drivername
, const char *arch
, uint32 version
)
2050 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver
;
2051 TDB_DATA kbuf
, dbuf
;
2052 const char *architecture
;
2057 ZERO_STRUCT(driver
);
2059 architecture
= get_short_archi(arch
);
2061 if ( !architecture
)
2062 return WERR_UNKNOWN_PRINTER_DRIVER
;
2064 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2066 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2069 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2071 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
, architecture
, version
, drivername
);
2074 kbuf
.dsize
= strlen(key
)+1;
2076 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
2078 return WERR_UNKNOWN_PRINTER_DRIVER
;
2080 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2089 driver
.defaultdatatype
);
2092 while (len
< dbuf
.dsize
) {
2095 tddfs
= SMB_REALLOC_ARRAY(driver
.dependentfiles
, fstring
, i
+2);
2097 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2101 driver
.dependentfiles
= tddfs
;
2103 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2104 &driver
.dependentfiles
[i
]);
2108 if ( driver
.dependentfiles
)
2109 fstrcpy( driver
.dependentfiles
[i
], "" );
2111 SAFE_FREE(dbuf
.dptr
);
2113 if (len
!= dbuf
.dsize
) {
2114 SAFE_FREE(driver
.dependentfiles
);
2116 return get_a_printer_driver_3_default(info_ptr
, drivername
, arch
);
2119 *info_ptr
= (NT_PRINTER_DRIVER_INFO_LEVEL_3
*)memdup(&driver
, sizeof(driver
));
2124 /****************************************************************************
2125 Debugging function, dump at level 6 the struct in the logs.
2126 ****************************************************************************/
2128 static uint32
dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2131 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
2134 DEBUG(20,("Dumping printer driver at level [%d]\n", level
));
2140 if (driver
.info_3
== NULL
)
2143 info3
=driver
.info_3
;
2145 DEBUGADD(20,("version:[%d]\n", info3
->cversion
));
2146 DEBUGADD(20,("name:[%s]\n", info3
->name
));
2147 DEBUGADD(20,("environment:[%s]\n", info3
->environment
));
2148 DEBUGADD(20,("driverpath:[%s]\n", info3
->driverpath
));
2149 DEBUGADD(20,("datafile:[%s]\n", info3
->datafile
));
2150 DEBUGADD(20,("configfile:[%s]\n", info3
->configfile
));
2151 DEBUGADD(20,("helpfile:[%s]\n", info3
->helpfile
));
2152 DEBUGADD(20,("monitorname:[%s]\n", info3
->monitorname
));
2153 DEBUGADD(20,("defaultdatatype:[%s]\n", info3
->defaultdatatype
));
2155 for (i
=0; info3
->dependentfiles
&&
2156 *info3
->dependentfiles
[i
]; i
++) {
2157 DEBUGADD(20,("dependentfile:[%s]\n",
2158 info3
->dependentfiles
[i
]));
2165 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level
));
2173 /****************************************************************************
2174 ****************************************************************************/
2175 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
2179 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2184 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2185 nt_devmode
->devicename
,
2186 nt_devmode
->formname
,
2188 nt_devmode
->specversion
,
2189 nt_devmode
->driverversion
,
2191 nt_devmode
->driverextra
,
2192 nt_devmode
->orientation
,
2193 nt_devmode
->papersize
,
2194 nt_devmode
->paperlength
,
2195 nt_devmode
->paperwidth
,
2198 nt_devmode
->defaultsource
,
2199 nt_devmode
->printquality
,
2202 nt_devmode
->yresolution
,
2203 nt_devmode
->ttoption
,
2204 nt_devmode
->collate
,
2205 nt_devmode
->logpixels
,
2208 nt_devmode
->bitsperpel
,
2209 nt_devmode
->pelswidth
,
2210 nt_devmode
->pelsheight
,
2211 nt_devmode
->displayflags
,
2212 nt_devmode
->displayfrequency
,
2213 nt_devmode
->icmmethod
,
2214 nt_devmode
->icmintent
,
2215 nt_devmode
->mediatype
,
2216 nt_devmode
->dithertype
,
2217 nt_devmode
->reserved1
,
2218 nt_devmode
->reserved2
,
2219 nt_devmode
->panningwidth
,
2220 nt_devmode
->panningheight
,
2221 nt_devmode
->nt_dev_private
);
2224 if (nt_devmode
->nt_dev_private
) {
2225 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2226 nt_devmode
->driverextra
,
2227 nt_devmode
->nt_dev_private
);
2230 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2235 /****************************************************************************
2236 Pack all values in all printer keys
2237 ***************************************************************************/
2239 static int pack_values(NT_PRINTER_DATA
*data
, char *buf
, int buflen
)
2243 REGISTRY_VALUE
*val
;
2244 REGVAL_CTR
*val_ctr
;
2251 /* loop over all keys */
2253 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2254 val_ctr
= data
->keys
[i
].values
;
2255 num_values
= regval_ctr_numvals( val_ctr
);
2257 /* pack the keyname followed by a empty value */
2259 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2260 &data
->keys
[i
].name
,
2266 /* now loop over all values */
2268 for ( j
=0; j
<num_values
; j
++ ) {
2269 /* pathname should be stored as <key>\<value> */
2271 val
= regval_ctr_specific_value( val_ctr
, j
);
2272 pstrcpy( path
, data
->keys
[i
].name
);
2273 pstrcat( path
, "\\" );
2274 pstrcat( path
, regval_name(val
) );
2276 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2281 regval_data_p(val
) );
2283 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2290 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2296 /****************************************************************************
2297 Delete a printer - this just deletes the printer info file, any open
2298 handles are not affected.
2299 ****************************************************************************/
2301 uint32
del_a_printer(const char *sharename
)
2305 pstring printdb_path
;
2307 slprintf(key
, sizeof(key
)-1, "%s%s", PRINTERS_PREFIX
, sharename
);
2309 kbuf
.dsize
=strlen(key
)+1;
2310 tdb_delete(tdb_printers
, kbuf
);
2312 slprintf(key
, sizeof(key
)-1, "%s%s", SECDESC_PREFIX
, sharename
);
2314 kbuf
.dsize
=strlen(key
)+1;
2315 tdb_delete(tdb_printers
, kbuf
);
2317 close_all_print_db();
2319 if (geteuid() == 0) {
2320 pstrcpy(printdb_path
, lock_path("printing/"));
2321 pstrcat(printdb_path
, sharename
);
2322 pstrcat(printdb_path
, ".tdb");
2324 unlink(printdb_path
);
2330 /****************************************************************************
2331 ****************************************************************************/
2332 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2337 TDB_DATA kbuf
, dbuf
;
2340 * in addprinter: no servername and the printer is the name
2341 * in setprinter: servername is \\server
2342 * and printer is \\server\\printer
2344 * Samba manages only local printers.
2345 * we currently don't support things like i
2346 * path=\\other_server\printer
2348 * We only store the printername, not \\server\printername
2351 if ( info
->servername
[0] != '\0' ) {
2352 trim_string(info
->printername
, info
->servername
, NULL
);
2353 trim_char(info
->printername
, '\\', '\0');
2354 info
->servername
[0]='\0';
2358 * JFM: one day I'll forget.
2359 * below that's info->portname because that's the SAMBA sharename
2360 * and I made NT 'thinks' it's the portname
2361 * the info->sharename is the thing you can name when you add a printer
2362 * that's the short-name when you create shared printer for 95/98
2363 * So I've made a limitation in SAMBA: you can only have 1 printer model
2364 * behind a SAMBA share.
2372 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2375 info
->default_priority
,
2392 info
->printprocessor
,
2396 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2398 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
2400 if (buflen
!= len
) {
2403 tb
= (char *)SMB_REALLOC(buf
, len
);
2405 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2415 kbuf
= make_printer_tdbkey( info
->sharename
);
2420 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2423 if (!W_ERROR_IS_OK(ret
))
2424 DEBUG(8, ("error updating printer to tdb on disk\n"));
2428 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2429 info
->sharename
, info
->drivername
, info
->portname
, len
));
2435 /****************************************************************************
2436 Malloc and return an NT devicemode.
2437 ****************************************************************************/
2439 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2442 char adevice
[MAXDEVICENAME
];
2443 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2445 if (nt_devmode
== NULL
) {
2446 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2450 ZERO_STRUCTP(nt_devmode
);
2452 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2453 fstrcpy(nt_devmode
->devicename
, adevice
);
2455 fstrcpy(nt_devmode
->formname
, "Letter");
2457 nt_devmode
->specversion
= 0x0401;
2458 nt_devmode
->driverversion
= 0x0400;
2459 nt_devmode
->size
= 0x00DC;
2460 nt_devmode
->driverextra
= 0x0000;
2461 nt_devmode
->fields
= FORMNAME
| TTOPTION
| PRINTQUALITY
|
2462 DEFAULTSOURCE
| COPIES
| SCALE
|
2463 PAPERSIZE
| ORIENTATION
;
2464 nt_devmode
->orientation
= 1;
2465 nt_devmode
->papersize
= PAPER_LETTER
;
2466 nt_devmode
->paperlength
= 0;
2467 nt_devmode
->paperwidth
= 0;
2468 nt_devmode
->scale
= 0x64;
2469 nt_devmode
->copies
= 1;
2470 nt_devmode
->defaultsource
= BIN_FORMSOURCE
;
2471 nt_devmode
->printquality
= RES_HIGH
; /* 0x0258 */
2472 nt_devmode
->color
= COLOR_MONOCHROME
;
2473 nt_devmode
->duplex
= DUP_SIMPLEX
;
2474 nt_devmode
->yresolution
= 0;
2475 nt_devmode
->ttoption
= TT_SUBDEV
;
2476 nt_devmode
->collate
= COLLATE_FALSE
;
2477 nt_devmode
->icmmethod
= 0;
2478 nt_devmode
->icmintent
= 0;
2479 nt_devmode
->mediatype
= 0;
2480 nt_devmode
->dithertype
= 0;
2482 /* non utilisés par un driver d'imprimante */
2483 nt_devmode
->logpixels
= 0;
2484 nt_devmode
->bitsperpel
= 0;
2485 nt_devmode
->pelswidth
= 0;
2486 nt_devmode
->pelsheight
= 0;
2487 nt_devmode
->displayflags
= 0;
2488 nt_devmode
->displayfrequency
= 0;
2489 nt_devmode
->reserved1
= 0;
2490 nt_devmode
->reserved2
= 0;
2491 nt_devmode
->panningwidth
= 0;
2492 nt_devmode
->panningheight
= 0;
2494 nt_devmode
->nt_dev_private
= NULL
;
2498 /****************************************************************************
2499 Deepcopy an NT devicemode.
2500 ****************************************************************************/
2502 NT_DEVICEMODE
*dup_nt_devicemode(NT_DEVICEMODE
*nt_devicemode
)
2504 NT_DEVICEMODE
*new_nt_devicemode
= NULL
;
2506 if ( !nt_devicemode
)
2509 if ((new_nt_devicemode
= (NT_DEVICEMODE
*)memdup(nt_devicemode
, sizeof(NT_DEVICEMODE
))) == NULL
) {
2510 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2514 new_nt_devicemode
->nt_dev_private
= NULL
;
2515 if (nt_devicemode
->nt_dev_private
!= NULL
) {
2516 if ((new_nt_devicemode
->nt_dev_private
= memdup(nt_devicemode
->nt_dev_private
, nt_devicemode
->driverextra
)) == NULL
) {
2517 SAFE_FREE(new_nt_devicemode
);
2518 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2523 return new_nt_devicemode
;
2526 /****************************************************************************
2527 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2528 ****************************************************************************/
2530 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2532 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2534 if(nt_devmode
== NULL
)
2537 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2539 SAFE_FREE(nt_devmode
->nt_dev_private
);
2540 SAFE_FREE(*devmode_ptr
);
2543 /****************************************************************************
2544 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2545 ****************************************************************************/
2547 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2549 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2554 free_nt_devicemode(&info
->devmode
);
2556 TALLOC_FREE( *info_ptr
);
2560 /****************************************************************************
2561 ****************************************************************************/
2562 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
2566 NT_DEVICEMODE devmode
;
2568 ZERO_STRUCT(devmode
);
2570 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2572 if (!*nt_devmode
) return len
;
2574 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2578 &devmode
.specversion
,
2579 &devmode
.driverversion
,
2581 &devmode
.driverextra
,
2582 &devmode
.orientation
,
2584 &devmode
.paperlength
,
2585 &devmode
.paperwidth
,
2588 &devmode
.defaultsource
,
2589 &devmode
.printquality
,
2592 &devmode
.yresolution
,
2598 &devmode
.bitsperpel
,
2600 &devmode
.pelsheight
,
2601 &devmode
.displayflags
,
2602 &devmode
.displayfrequency
,
2606 &devmode
.dithertype
,
2609 &devmode
.panningwidth
,
2610 &devmode
.panningheight
,
2611 &devmode
.nt_dev_private
);
2613 if (devmode
.nt_dev_private
) {
2614 /* the len in tdb_unpack is an int value and
2615 * devmode.driverextra is only a short
2617 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2618 devmode
.driverextra
=(uint16
)extra_len
;
2620 /* check to catch an invalid TDB entry so we don't segfault */
2621 if (devmode
.driverextra
== 0) {
2622 devmode
.nt_dev_private
= NULL
;
2626 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2628 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2629 if (devmode
.nt_dev_private
)
2630 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2635 /****************************************************************************
2636 Allocate and initialize a new slot.
2637 ***************************************************************************/
2639 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2644 if ( !name
|| !data
)
2647 /* allocate another slot in the NT_PRINTER_KEY array */
2649 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2650 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2656 key_index
= data
->num_keys
;
2658 /* initialze new key */
2660 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2662 if ( !(data
->keys
[key_index
].values
= TALLOC_ZERO_P( data
, REGVAL_CTR
)) )
2667 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2672 /****************************************************************************
2673 search for a registry key name in the existing printer data
2674 ***************************************************************************/
2676 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2680 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2681 if ( strequal( data
->keys
[i
].name
, name
) ) {
2683 /* cleanup memory */
2685 TALLOC_FREE( data
->keys
[i
].name
);
2686 TALLOC_FREE( data
->keys
[i
].values
);
2688 /* if not the end of the array, move remaining elements down one slot */
2691 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2692 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2699 return data
->num_keys
;
2702 /****************************************************************************
2703 search for a registry key name in the existing printer data
2704 ***************************************************************************/
2706 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2711 if ( !data
|| !name
)
2714 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2716 /* loop over all existing keys */
2718 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2719 if ( strequal(data
->keys
[i
].name
, name
) ) {
2720 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2730 /****************************************************************************
2731 ***************************************************************************/
2733 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2737 int num_subkeys
= 0;
2739 fstring
*ptr
, *subkeys_ptr
= NULL
;
2748 /* special case of asking for the top level printer data registry key names */
2750 if ( strlen(key
) == 0 ) {
2751 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2753 /* found a match, so allocate space and copy the name */
2755 if ( !(ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2756 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2758 SAFE_FREE( subkeys
);
2763 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2770 /* asking for the subkeys of some key */
2771 /* subkey paths are stored in the key name using '\' as the delimiter */
2773 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2774 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2776 /* if we found the exact key, then break */
2777 key_len
= strlen( key
);
2778 if ( strlen(data
->keys
[i
].name
) == key_len
)
2781 /* get subkey path */
2783 p
= data
->keys
[i
].name
+ key_len
;
2786 fstrcpy( subkeyname
, p
);
2787 if ( (p
= strchr( subkeyname
, '\\' )) )
2790 /* don't add a key more than once */
2792 for ( j
=0; j
<num_subkeys
; j
++ ) {
2793 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2797 if ( j
!= num_subkeys
)
2800 /* found a match, so allocate space and copy the name */
2802 if ( !(ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2803 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2805 SAFE_FREE( subkeys
);
2810 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2816 /* return error if the key was not found */
2818 if ( i
== data
->num_keys
)
2822 /* tag off the end */
2825 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2827 *subkeys
= subkeys_ptr
;
2833 static void map_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2836 smb_ucs2_t conv_str
[1024];
2839 regval_ctr_delvalue(ctr
, val_name
);
2840 str_size
= push_ucs2(NULL
, conv_str
, sz
, sizeof(conv_str
),
2841 STR_TERMINATE
| STR_NOALIGN
);
2842 regval_ctr_addvalue(ctr
, val_name
, REG_SZ
,
2843 (char *) conv_str
, str_size
);
2846 static void map_dword_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2849 regval_ctr_delvalue(ctr
, val_name
);
2850 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2851 (char *) &dword
, sizeof(dword
));
2854 static void map_bool_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2857 uint8 bin_bool
= (b
? 1 : 0);
2858 regval_ctr_delvalue(ctr
, val_name
);
2859 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2860 (char *) &bin_bool
, sizeof(bin_bool
));
2863 static void map_single_multi_sz_into_ctr(REGVAL_CTR
*ctr
, const char *val_name
,
2864 const char *multi_sz
)
2866 smb_ucs2_t
*conv_strs
= NULL
;
2869 /* a multi-sz has to have a null string terminator, i.e., the last
2870 string must be followed by two nulls */
2871 str_size
= strlen(multi_sz
) + 2;
2872 conv_strs
= SMB_CALLOC_ARRAY(smb_ucs2_t
, str_size
);
2877 /* Change to byte units. */
2878 str_size
*= sizeof(smb_ucs2_t
);
2879 push_ucs2(NULL
, conv_strs
, multi_sz
, str_size
,
2880 STR_TERMINATE
| STR_NOALIGN
);
2882 regval_ctr_delvalue(ctr
, val_name
);
2883 regval_ctr_addvalue(ctr
, val_name
, REG_MULTI_SZ
,
2884 (char *) conv_strs
, str_size
);
2885 safe_free(conv_strs
);
2889 /****************************************************************************
2890 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2892 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2893 * @return BOOL indicating success or failure
2894 ***************************************************************************/
2896 static BOOL
map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
2898 REGVAL_CTR
*ctr
= NULL
;
2901 char *allocated_string
= NULL
;
2902 const char *ascii_str
;
2905 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2906 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
2907 ctr
= info2
->data
->keys
[i
].values
;
2909 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
2910 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
2912 /* we make the assumption that the netbios name is the same
2913 as the DNS name sinc ethe former will be what we used to
2916 if ( get_mydnsdomname( dnssuffix
) )
2917 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
2919 fstrcpy( longname
, global_myname() );
2921 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
2923 asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
);
2924 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
2925 SAFE_FREE(allocated_string
);
2927 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
2928 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
2929 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
2930 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
2931 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
2932 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
2933 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
2934 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
2935 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
2937 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
2938 (info2
->attributes
&
2939 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
2941 switch (info2
->attributes
& 0x3) {
2943 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
2946 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
2949 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
2952 ascii_str
= "unknown";
2954 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
2959 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
2963 REGVAL_CTR
*ctr
=NULL
;
2965 /* find the DsSpooler key */
2966 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
2967 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
2968 ctr
= info2
->data
->keys
[i
].values
;
2970 regval_ctr_delvalue(ctr
, "objectGUID");
2971 regval_ctr_addvalue(ctr
, "objectGUID", REG_BINARY
,
2972 (char *) &guid
, sizeof(struct uuid
));
2975 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
2976 NT_PRINTER_INFO_LEVEL
*printer
)
2980 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
;
2981 char *srv_dn_utf8
, **srv_cn_utf8
;
2984 const char *attrs
[] = {"objectGUID", NULL
};
2986 WERROR win_rc
= WERR_OK
;
2988 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
2990 /* figure out where to publish */
2991 ads_find_machine_acct(ads
, &res
, global_myname());
2993 /* We use ldap_get_dn here as we need the answer
2994 * in utf8 to call ldap_explode_dn(). JRA. */
2996 srv_dn_utf8
= ldap_get_dn(ads
->ld
, res
);
2999 return WERR_SERVER_UNAVAILABLE
;
3001 ads_msgfree(ads
, res
);
3002 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3004 ldap_memfree(srv_dn_utf8
);
3006 return WERR_SERVER_UNAVAILABLE
;
3008 /* Now convert to CH_UNIX. */
3009 if (pull_utf8_allocate(&srv_dn
, srv_dn_utf8
) == (size_t)-1) {
3010 ldap_memfree(srv_dn_utf8
);
3011 ldap_memfree(srv_cn_utf8
);
3013 return WERR_SERVER_UNAVAILABLE
;
3015 if (pull_utf8_allocate(&srv_cn_0
, srv_cn_utf8
[0]) == (size_t)-1) {
3016 ldap_memfree(srv_dn_utf8
);
3017 ldap_memfree(srv_cn_utf8
);
3020 return WERR_SERVER_UNAVAILABLE
;
3023 ldap_memfree(srv_dn_utf8
);
3024 ldap_memfree(srv_cn_utf8
);
3026 asprintf(&prt_dn
, "cn=%s-%s,%s", srv_cn_0
,
3027 printer
->info_2
->sharename
, srv_dn
);
3030 SAFE_FREE(srv_cn_0
);
3032 /* build the ads mods */
3033 ctx
= talloc_init("nt_printer_publish_ads");
3034 mods
= ads_init_mods(ctx
);
3036 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3037 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3038 printer
->info_2
->sharename
);
3041 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3042 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
)
3043 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3045 if (!ADS_ERR_OK(ads_rc
))
3046 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3048 talloc_destroy(ctx
);
3050 /* retreive the guid and store it locally */
3051 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3053 ads_pull_guid(ads
, res
, &guid
);
3054 ads_msgfree(ads
, res
);
3055 store_printer_guid(printer
->info_2
, guid
);
3056 win_rc
= mod_a_printer(printer
, 2);
3063 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3064 NT_PRINTER_INFO_LEVEL
*printer
)
3068 char *prt_dn
= NULL
;
3070 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3072 /* remove the printer from the directory */
3073 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3074 printer
->info_2
->sharename
, global_myname());
3076 if (ADS_ERR_OK(ads_rc
) && ads_count_replies(ads
, res
)) {
3077 prt_dn
= ads_get_dn(ads
, res
);
3078 ads_rc
= ads_del_dn(ads
, prt_dn
);
3079 ads_memfree(ads
, prt_dn
);
3082 ads_msgfree(ads
, res
);
3086 /****************************************************************************
3087 * Publish a printer in the directory
3089 * @param snum describing printer service
3090 * @return WERROR indicating status of publishing
3091 ***************************************************************************/
3093 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3096 ADS_STRUCT
*ads
= NULL
;
3097 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3100 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3101 if (!W_ERROR_IS_OK(win_rc
))
3105 case SPOOL_DS_PUBLISH
:
3106 case SPOOL_DS_UPDATE
:
3107 /* set the DsSpooler info and attributes */
3108 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3109 win_rc
= WERR_NOMEM
;
3113 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3115 case SPOOL_DS_UNPUBLISH
:
3116 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3119 win_rc
= WERR_NOT_SUPPORTED
;
3123 win_rc
= mod_a_printer(printer
, 2);
3124 if (!W_ERROR_IS_OK(win_rc
)) {
3125 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3129 ads
= ads_init(NULL
, NULL
, NULL
);
3131 DEBUG(3, ("ads_init() failed\n"));
3132 win_rc
= WERR_SERVER_UNAVAILABLE
;
3135 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3136 SAFE_FREE(ads
->auth
.password
);
3137 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3140 /* ads_connect() will find the DC for us */
3141 ads_rc
= ads_connect(ads
);
3142 if (!ADS_ERR_OK(ads_rc
)) {
3143 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3144 win_rc
= WERR_ACCESS_DENIED
;
3149 case SPOOL_DS_PUBLISH
:
3150 case SPOOL_DS_UPDATE
:
3151 win_rc
= nt_printer_publish_ads(ads
, printer
);
3153 case SPOOL_DS_UNPUBLISH
:
3154 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3159 free_a_printer(&printer
, 2);
3164 WERROR
check_published_printers(void)
3167 ADS_STRUCT
*ads
= NULL
;
3169 int n_services
= lp_numservices();
3170 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3172 ads
= ads_init(NULL
, NULL
, NULL
);
3174 DEBUG(3, ("ads_init() failed\n"));
3175 return WERR_SERVER_UNAVAILABLE
;
3177 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3178 SAFE_FREE(ads
->auth
.password
);
3179 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3182 /* ads_connect() will find the DC for us */
3183 ads_rc
= ads_connect(ads
);
3184 if (!ADS_ERR_OK(ads_rc
)) {
3185 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3187 return WERR_ACCESS_DENIED
;
3190 for (snum
= 0; snum
< n_services
; snum
++) {
3191 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3194 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3195 lp_servicename(snum
))) &&
3196 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3197 nt_printer_publish_ads(ads
, printer
);
3199 free_a_printer(&printer
, 2);
3206 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3209 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3211 REGISTRY_VALUE
*guid_val
;
3215 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3217 if (!W_ERROR_IS_OK(win_rc
) ||
3218 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3219 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3220 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3221 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3223 free_a_printer(&printer
, 2);
3227 /* fetching printer guids really ought to be a separate function.. */
3228 if (guid
&& regval_size(guid_val
) == sizeof(struct uuid
))
3229 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct uuid
));
3231 free_a_printer(&printer
, 2);
3235 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3240 WERROR
check_published_printers(void)
3245 BOOL
is_printer_published(Printer_entry
*print_hnd
, int snum
,
3250 #endif /* HAVE_ADS */
3252 /****************************************************************************
3253 ***************************************************************************/
3255 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3257 NT_PRINTER_DATA
*data
;
3259 int removed_keys
= 0;
3263 empty_slot
= data
->num_keys
;
3266 return WERR_INVALID_PARAM
;
3268 /* remove all keys */
3270 if ( !strlen(key
) ) {
3272 TALLOC_FREE( data
);
3274 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3280 /* remove a specific key (and all subkeys) */
3282 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3283 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3284 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3285 data
->keys
[i
].name
));
3287 TALLOC_FREE( data
->keys
[i
].name
);
3288 TALLOC_FREE( data
->keys
[i
].values
);
3290 /* mark the slot as empty */
3292 ZERO_STRUCTP( &data
->keys
[i
] );
3296 /* find the first empty slot */
3298 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3299 if ( !data
->keys
[i
].name
) {
3306 if ( i
== data
->num_keys
)
3307 /* nothing was removed */
3308 return WERR_INVALID_PARAM
;
3310 /* move everything down */
3312 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3313 if ( data
->keys
[i
].name
) {
3314 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3315 ZERO_STRUCTP( &data
->keys
[i
] );
3323 data
->num_keys
-= removed_keys
;
3325 /* sanity check to see if anything is left */
3327 if ( !data
->num_keys
) {
3328 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3330 SAFE_FREE( data
->keys
);
3331 ZERO_STRUCTP( data
);
3337 /****************************************************************************
3338 ***************************************************************************/
3340 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3342 WERROR result
= WERR_OK
;
3345 /* we must have names on non-zero length */
3347 if ( !key
|| !*key
|| !value
|| !*value
)
3348 return WERR_INVALID_NAME
;
3350 /* find the printer key first */
3352 key_index
= lookup_printerkey( p2
->data
, key
);
3353 if ( key_index
== -1 )
3356 /* make sure the value exists so we can return the correct error code */
3358 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3359 return WERR_BADFILE
;
3361 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3363 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3369 /****************************************************************************
3370 ***************************************************************************/
3372 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3373 uint32 type
, uint8
*data
, int real_len
)
3375 WERROR result
= WERR_OK
;
3378 /* we must have names on non-zero length */
3380 if ( !key
|| !*key
|| !value
|| !*value
)
3381 return WERR_INVALID_NAME
;
3383 /* find the printer key first */
3385 key_index
= lookup_printerkey( p2
->data
, key
);
3386 if ( key_index
== -1 )
3387 key_index
= add_new_printer_key( p2
->data
, key
);
3389 if ( key_index
== -1 )
3392 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3393 type
, (const char *)data
, real_len
);
3395 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3396 key
, value
, type
, real_len
));
3401 /****************************************************************************
3402 ***************************************************************************/
3404 REGISTRY_VALUE
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3408 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3411 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3414 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3417 /****************************************************************************
3418 Unpack a list of registry values frem the TDB
3419 ***************************************************************************/
3421 static int unpack_values(NT_PRINTER_DATA
*printer_data
, char *buf
, int buflen
)
3425 pstring string
, valuename
, keyname
;
3429 REGISTRY_VALUE
*regval_p
;
3432 /* add the "PrinterDriverData" key first for performance reasons */
3434 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3436 /* loop and unpack the rest of the registry values */
3440 /* check to see if there are any more registry values */
3443 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3447 /* unpack the next regval */
3449 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3455 /* lookup for subkey names which have a type of REG_NONE */
3456 /* there's no data with this entry */
3458 if ( type
== REG_NONE
) {
3459 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3460 add_new_printer_key( printer_data
, string
);
3465 * break of the keyname from the value name.
3466 * Valuenames can have embedded '\'s so be careful.
3467 * only support one level of keys. See the
3468 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3472 str
= strchr_m( string
, '\\');
3474 /* Put in "PrinterDriverData" is no key specified */
3477 pstrcpy( keyname
, SPOOL_PRINTERDATA_KEY
);
3478 pstrcpy( valuename
, string
);
3482 pstrcpy( keyname
, string
);
3483 pstrcpy( valuename
, str
+1 );
3486 /* see if we need a new key */
3488 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3489 key_index
= add_new_printer_key( printer_data
, keyname
);
3491 if ( key_index
== -1 ) {
3492 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3497 /* add the new value */
3499 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
, valuename
, type
, (const char *)data_p
, size
);
3501 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3503 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3509 /****************************************************************************
3510 ***************************************************************************/
3512 static void map_to_os2_driver(fstring drivername
)
3514 static BOOL initialised
=False
;
3515 static fstring last_from
,last_to
;
3516 char *mapfile
= lp_os2_driver_map();
3517 char **lines
= NULL
;
3521 if (!strlen(drivername
))
3528 *last_from
= *last_to
= 0;
3532 if (strequal(drivername
,last_from
)) {
3533 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,last_to
));
3534 fstrcpy(drivername
,last_to
);
3538 lines
= file_lines_load(mapfile
, &numlines
);
3539 if (numlines
== 0) {
3540 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3544 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3546 for( i
= 0; i
< numlines
; i
++) {
3547 char *nt_name
= lines
[i
];
3548 char *os2_name
= strchr(nt_name
,'=');
3555 while (isspace(*nt_name
))
3558 if (!*nt_name
|| strchr("#;",*nt_name
))
3562 int l
= strlen(nt_name
);
3563 while (l
&& isspace(nt_name
[l
-1])) {
3569 while (isspace(*os2_name
))
3573 int l
= strlen(os2_name
);
3574 while (l
&& isspace(os2_name
[l
-1])) {
3580 if (strequal(nt_name
,drivername
)) {
3581 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3582 fstrcpy(last_from
,drivername
);
3583 fstrcpy(last_to
,os2_name
);
3584 fstrcpy(drivername
,os2_name
);
3585 file_lines_free(lines
);
3590 file_lines_free(lines
);
3593 /****************************************************************************
3594 Get a default printer info 2 struct.
3595 ****************************************************************************/
3596 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char* sharename
)
3600 snum
= lp_servicenumber(sharename
);
3602 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3603 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
3604 servername
, sharename
);
3605 fstrcpy(info
->sharename
, sharename
);
3606 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
3608 /* by setting the driver name to an empty string, a local NT admin
3609 can now run the **local** APW to install a local printer driver
3610 for a Samba shared printer in 2.2. Without this, drivers **must** be
3611 installed on the Samba server for NT clients --jerry */
3612 #if 0 /* JERRY --do not uncomment-- */
3613 if (!*info
->drivername
)
3614 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3618 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
3620 pstrcpy(info
->comment
, "");
3621 fstrcpy(info
->printprocessor
, "winprint");
3622 fstrcpy(info
->datatype
, "RAW");
3624 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3626 info
->starttime
= 0; /* Minutes since 12:00am GMT */
3627 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
3629 info
->default_priority
= 1;
3630 info
->setuptime
= (uint32
)time(NULL
);
3633 * I changed this as I think it is better to have a generic
3634 * DEVMODE than to crash Win2k explorer.exe --jerry
3635 * See the HP Deskjet 990c Win2k drivers for an example.
3637 * However the default devmode appears to cause problems
3638 * with the HP CLJ 8500 PCL driver. Hence the addition of
3639 * the "default devmode" parameter --jerry 22/01/2002
3642 if (lp_default_devmode(snum
)) {
3643 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
)
3647 info
->devmode
= NULL
;
3650 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
))
3657 free_nt_devicemode(&info
->devmode
);
3659 return WERR_ACCESS_DENIED
;
3662 /****************************************************************************
3663 ****************************************************************************/
3664 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
, const char *servername
, const char *sharename
)
3667 int snum
= lp_servicenumber(sharename
);
3668 TDB_DATA kbuf
, dbuf
;
3669 fstring printername
;
3670 char adevice
[MAXDEVICENAME
];
3672 kbuf
= make_printer_tdbkey( sharename
);
3674 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3676 return get_a_printer_2_default(info
, servername
, sharename
);
3678 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3681 &info
->default_priority
,
3688 &info
->c_setprinter
,
3698 info
->printprocessor
,
3702 /* Samba has to have shared raw drivers. */
3703 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3704 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3706 /* Restore the stripped strings. */
3707 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3709 if ( lp_force_printername(snum
) )
3710 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3712 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
3714 fstrcpy(info
->printername
, printername
);
3716 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3719 * Some client drivers freak out if there is a NULL devmode
3720 * (probably the driver is not checking before accessing
3721 * the devmode pointer) --jerry
3723 * See comments in get_a_printer_2_default()
3726 if (lp_default_devmode(snum
) && !info
->devmode
) {
3727 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3729 info
->devmode
= construct_nt_devicemode(printername
);
3732 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
3733 if (info
->devmode
) {
3734 fstrcpy(info
->devmode
->devicename
, adevice
);
3737 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
3738 DEBUG(0,("unpack_values: talloc() failed!\n"));
3741 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3743 /* This will get the current RPC talloc context, but we should be
3744 passing this as a parameter... fixme... JRA ! */
3746 nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
);
3748 /* Fix for OS/2 drivers. */
3750 if (get_remote_arch() == RA_OS2
)
3751 map_to_os2_driver(info
->drivername
);
3753 SAFE_FREE(dbuf
.dptr
);
3755 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3756 sharename
, info
->printername
, info
->drivername
));
3761 /****************************************************************************
3762 Debugging function, dump at level 6 the struct in the logs.
3763 ****************************************************************************/
3764 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3767 NT_PRINTER_INFO_LEVEL_2
*info2
;
3769 DEBUG(106,("Dumping printer at level [%d]\n", level
));
3774 if (printer
->info_2
== NULL
)
3778 info2
=printer
->info_2
;
3780 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
3781 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
3782 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
3783 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
3784 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
3785 DEBUGADD(106,("status:[%d]\n", info2
->status
));
3786 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
3787 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
3788 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
3789 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
3790 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
3792 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
3793 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
3794 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
3795 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
3796 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
3797 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
3798 DEBUGADD(106,("location:[%s]\n", info2
->location
));
3799 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
3800 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
3801 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
3802 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
3808 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
3816 /****************************************************************************
3817 Update the changeid time.
3818 This is SO NASTY as some drivers need this to change, others need it
3819 static. This value will change every second, and I must hope that this
3820 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3822 ****************************************************************************/
3824 static uint32
rev_changeid(void)
3828 get_process_uptime(&tv
);
3831 /* Return changeid as msec since spooler restart */
3832 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
3835 * This setting seems to work well but is too untested
3836 * to replace the above calculation. Left in for experiementation
3837 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3839 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
3845 * The function below are the high level ones.
3846 * only those ones must be called from the spoolss code.
3850 /****************************************************************************
3851 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3852 ****************************************************************************/
3854 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
3858 dump_a_printer(printer
, level
);
3864 * Update the changestamp. Emperical tests show that the
3865 * ChangeID is always updated,but c_setprinter is
3866 * global spooler variable (not per printer).
3869 /* ChangeID **must** be increasing over the lifetime
3870 of client's spoolss service in order for the
3871 client's cache to show updates */
3873 printer
->info_2
->changeid
= rev_changeid();
3876 * Because one day someone will ask:
3877 * NT->NT An admin connection to a remote
3878 * printer show changes imeediately in
3879 * the properities dialog
3881 * A non-admin connection will only show the
3882 * changes after viewing the properites page
3883 * 2 times. Seems to be related to a
3884 * race condition in the client between the spooler
3885 * updating the local cache and the Explorer.exe GUI
3886 * actually displaying the properties.
3888 * This is fixed in Win2k. admin/non-admin
3889 * connections both display changes immediately.
3894 result
=update_a_printer_2(printer
->info_2
);
3899 result
=WERR_UNKNOWN_LEVEL
;
3906 /****************************************************************************
3907 Initialize printer devmode & data with previously saved driver init values.
3908 ****************************************************************************/
3910 static BOOL
set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
3914 TDB_DATA kbuf
, dbuf
;
3915 NT_PRINTER_INFO_LEVEL_2 info
;
3921 * Delete any printer data 'values' already set. When called for driver
3922 * replace, there will generally be some, but during an add printer, there
3923 * should not be any (if there are delete them).
3926 if ( info_ptr
->data
)
3927 delete_all_printer_data( info_ptr
, "" );
3929 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info_ptr
->drivername
);
3932 kbuf
.dsize
= strlen(key
)+1;
3934 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
3937 * When changing to a driver that has no init info in the tdb, remove
3938 * the previous drivers init info and leave the new on blank.
3940 free_nt_devicemode(&info_ptr
->devmode
);
3945 * Get the saved DEVMODE..
3948 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3951 * The saved DEVMODE contains the devicename from the printer used during
3952 * the initialization save. Change it to reflect the new printer.
3955 if ( info
.devmode
) {
3956 ZERO_STRUCT(info
.devmode
->devicename
);
3957 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
3961 * NT/2k does not change out the entire DeviceMode of a printer
3962 * when changing the driver. Only the driverextra, private, &
3963 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3965 * Later examination revealed that Windows NT/2k does reset the
3966 * the printer's device mode, bit **only** when you change a
3967 * property of the device mode such as the page orientation.
3972 /* Bind the saved DEVMODE to the new the printer */
3974 free_nt_devicemode(&info_ptr
->devmode
);
3975 info_ptr
->devmode
= info
.devmode
;
3977 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3978 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
3980 /* Add the printer data 'values' to the new printer */
3982 if ( !(info_ptr
->data
= TALLOC_ZERO_P( info_ptr
, NT_PRINTER_DATA
)) ) {
3983 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
3987 len
+= unpack_values( info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
3990 SAFE_FREE(dbuf
.dptr
);
3995 /****************************************************************************
3996 Initialize printer devmode & data with previously saved driver init values.
3997 When a printer is created using AddPrinter, the drivername bound to the
3998 printer is used to lookup previously saved driver initialization info, which
3999 is bound to the new printer.
4000 ****************************************************************************/
4002 BOOL
set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4004 BOOL result
= False
;
4008 result
= set_driver_init_2(printer
->info_2
);
4012 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4020 /****************************************************************************
4021 Delete driver init data stored for a specified driver
4022 ****************************************************************************/
4024 BOOL
del_driver_init(char *drivername
)
4029 if (!drivername
|| !*drivername
) {
4030 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4034 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, drivername
);
4037 kbuf
.dsize
= strlen(key
)+1;
4039 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername
));
4041 return (tdb_delete(tdb_drivers
, kbuf
) == 0);
4044 /****************************************************************************
4045 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4046 in the tdb. Note: this is different from the driver entry and the printer
4047 entry. There should be a single driver init entry for each driver regardless
4048 of whether it was installed from NT or 2K. Technically, they should be
4049 different, but they work out to the same struct.
4050 ****************************************************************************/
4052 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4056 int buflen
, len
, ret
;
4057 TDB_DATA kbuf
, dbuf
;
4064 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4066 len
+= pack_values( info
->data
, buf
+len
, buflen
-len
);
4071 tb
= (char *)SMB_REALLOC(buf
, len
);
4073 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4083 slprintf(key
, sizeof(key
)-1, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
);
4086 kbuf
.dsize
= strlen(key
)+1;
4090 ret
= tdb_store(tdb_drivers
, kbuf
, dbuf
, TDB_REPLACE
);
4094 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4098 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4099 info
->sharename
, info
->drivername
));
4104 /****************************************************************************
4105 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4106 ****************************************************************************/
4108 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4112 dump_a_printer(printer
, level
);
4116 result
= update_driver_init_2(printer
->info_2
);
4126 /****************************************************************************
4127 Convert the printer data value, a REG_BINARY array, into an initialization
4128 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4129 got to keep the endians happy :).
4130 ****************************************************************************/
4132 static BOOL
convert_driver_init( TALLOC_CTX
*ctx
, NT_DEVICEMODE
*nt_devmode
, uint8
*data
, uint32 data_len
)
4134 BOOL result
= False
;
4138 ZERO_STRUCT(devmode
);
4140 prs_init(&ps
, 0, ctx
, UNMARSHALL
);
4141 ps
.data_p
= (char *)data
;
4142 ps
.buffer_size
= data_len
;
4144 if (spoolss_io_devmode("phantom DEVMODE", &ps
, 0, &devmode
))
4145 result
= convert_devicemode("", &devmode
, &nt_devmode
);
4147 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4152 /****************************************************************************
4153 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4155 1. Use the driver's config DLL to this UNC printername and:
4156 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4157 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4158 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4160 The last step triggers saving the "driver initialization" information for
4161 this printer into the tdb. Later, new printers that use this driver will
4162 have this initialization information bound to them. This simulates the
4163 driver initialization, as if it had run on the Samba server (as it would
4166 The Win32 client side code requirement sucks! But until we can run arbitrary
4167 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4169 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4170 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4171 about it and you will realize why. JRR 010720
4172 ****************************************************************************/
4174 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4176 WERROR status
= WERR_OK
;
4177 TALLOC_CTX
*ctx
= NULL
;
4178 NT_DEVICEMODE
*nt_devmode
= NULL
;
4179 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4182 * When the DEVMODE is already set on the printer, don't try to unpack it.
4184 DEBUG(8,("save_driver_init_2: Enter...\n"));
4186 if ( !printer
->info_2
->devmode
&& data_len
) {
4188 * Set devmode on printer info, so entire printer initialization can be
4192 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4195 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4196 status
= WERR_NOMEM
;
4200 ZERO_STRUCTP(nt_devmode
);
4203 * The DEVMODE is held in the 'data' component of the param in raw binary.
4204 * Convert it to to a devmode structure
4206 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4207 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4208 status
= WERR_INVALID_PARAM
;
4212 printer
->info_2
->devmode
= nt_devmode
;
4216 * Pack up and add (or update) the DEVMODE and any current printer data to
4217 * a 'driver init' element in the tdb
4221 if ( update_driver_init(printer
, 2) != 0 ) {
4222 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4223 status
= WERR_NOMEM
;
4228 * If driver initialization info was successfully saved, set the current
4229 * printer to match it. This allows initialization of the current printer
4230 * as well as the driver.
4232 status
= mod_a_printer(printer
, 2);
4233 if (!W_ERROR_IS_OK(status
)) {
4234 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4235 printer
->info_2
->printername
));
4239 talloc_destroy(ctx
);
4240 free_nt_devicemode( &nt_devmode
);
4242 printer
->info_2
->devmode
= tmp_devmode
;
4247 /****************************************************************************
4248 Update the driver init info (DEVMODE and specifics) for a printer
4249 ****************************************************************************/
4251 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4253 WERROR status
= WERR_OK
;
4257 status
= save_driver_init_2( printer
, data
, data_len
);
4260 status
= WERR_UNKNOWN_LEVEL
;
4267 /****************************************************************************
4268 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4270 Previously the code had a memory allocation problem because it always
4271 used the TALLOC_CTX from the Printer_entry*. This context lasts
4272 as a long as the original handle is open. So if the client made a lot
4273 of getprinter[data]() calls, the memory usage would climb. Now we use
4274 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4275 still use the Printer_entry->ctx for maintaining the cache copy though
4276 since that object must live as long as the handle by definition.
4279 ****************************************************************************/
4281 WERROR
get_a_printer( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4282 const char *sharename
)
4287 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4289 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4290 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4296 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4297 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4298 TALLOC_FREE( *pp_printer
);
4303 fstrcpy( servername
, print_hnd
->servername
);
4305 fstrcpy( servername
, "%L" );
4306 standard_sub_basic( "", servername
, sizeof(servername
)-1 );
4309 result
= get_a_printer_2( (*pp_printer
)->info_2
, servername
, sharename
);
4312 /* we have a new printer now. Save it with this handle */
4314 if ( !W_ERROR_IS_OK(result
) ) {
4315 TALLOC_FREE( *pp_printer
);
4316 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4317 sharename
, (unsigned int)level
, dos_errstr(result
)));
4321 dump_a_printer( *pp_printer
, level
);
4326 TALLOC_FREE( *pp_printer
);
4327 return WERR_UNKNOWN_LEVEL
;
4333 /****************************************************************************
4334 Deletes a NT_PRINTER_INFO_LEVEL struct.
4335 ****************************************************************************/
4337 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4339 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4346 if ( printer
->info_2
)
4347 free_nt_printer_info_level_2(&printer
->info_2
);
4351 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4355 TALLOC_FREE(*pp_printer
);
4360 /****************************************************************************
4361 ****************************************************************************/
4362 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4365 DEBUG(104,("adding a printer at level [%d]\n", level
));
4366 dump_a_printer_driver(driver
, level
);
4370 result
=add_a_printer_driver_3(driver
.info_3
);
4374 result
=add_a_printer_driver_6(driver
.info_6
);
4384 /****************************************************************************
4385 ****************************************************************************/
4387 WERROR
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
4388 fstring drivername
, const char *architecture
, uint32 version
)
4394 /* Sometime we just want any version of the driver */
4396 if ( version
== DRIVER_ANY_VERSION
) {
4397 /* look for Win2k first and then for NT4 */
4398 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4401 if ( !W_ERROR_IS_OK(result
) ) {
4402 result
= get_a_printer_driver_3( &driver
->info_3
,
4403 drivername
, architecture
, 2 );
4406 result
= get_a_printer_driver_3(&driver
->info_3
, drivername
,
4407 architecture
, version
);
4416 if (W_ERROR_IS_OK(result
))
4417 dump_a_printer_driver(*driver
, level
);
4422 /****************************************************************************
4423 ****************************************************************************/
4424 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
4431 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
4432 if (driver
.info_3
!= NULL
)
4434 info3
=driver
.info_3
;
4435 SAFE_FREE(info3
->dependentfiles
);
4436 ZERO_STRUCTP(info3
);
4446 NT_PRINTER_DRIVER_INFO_LEVEL_6
*info6
;
4447 if (driver
.info_6
!= NULL
) {
4448 info6
=driver
.info_6
;
4449 SAFE_FREE(info6
->dependentfiles
);
4450 SAFE_FREE(info6
->previousnames
);
4451 ZERO_STRUCTP(info6
);
4467 /****************************************************************************
4468 Determine whether or not a particular driver is currently assigned
4470 ****************************************************************************/
4472 BOOL
printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
)
4475 int n_services
= lp_numservices();
4476 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4477 BOOL in_use
= False
;
4482 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4484 /* loop through the printers.tdb and check for the drivername */
4486 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4487 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4490 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4493 if ( strequal(info_3
->name
, printer
->info_2
->drivername
) )
4496 free_a_printer( &printer
, 2 );
4499 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4502 NT_PRINTER_DRIVER_INFO_LEVEL d
;
4505 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3
->name
));
4507 /* we can still remove the driver if there is one of
4508 "Windows NT x86" version 2 or 3 left */
4510 if ( !strequal( "Windows NT x86", info_3
->environment
) ) {
4511 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4514 switch ( info_3
->cversion
) {
4516 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 3 );
4519 werr
= get_a_printer_driver( &d
, 3, info_3
->name
, "Windows NT x86", 2 );
4522 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4524 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4529 /* now check the error code */
4531 if ( W_ERROR_IS_OK(werr
) ) {
4532 /* it's ok to remove the driver, we have other architctures left */
4534 free_a_printer_driver( d
, 3 );
4538 /* report that the driver is not in use by default */
4544 /**********************************************************************
4545 Check to see if a ogiven file is in use by *info
4546 *********************************************************************/
4548 static BOOL
drv_file_in_use( char* file
, NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4555 if ( strequal(file
, info
->driverpath
) )
4558 if ( strequal(file
, info
->datafile
) )
4561 if ( strequal(file
, info
->configfile
) )
4564 if ( strequal(file
, info
->helpfile
) )
4567 /* see of there are any dependent files to examine */
4569 if ( !info
->dependentfiles
)
4572 while ( *info
->dependentfiles
[i
] ) {
4573 if ( strequal(file
, info
->dependentfiles
[i
]) )
4582 /**********************************************************************
4583 Utility function to remove the dependent file pointed to by the
4584 input parameter from the list
4585 *********************************************************************/
4587 static void trim_dependent_file( fstring files
[], int idx
)
4590 /* bump everything down a slot */
4592 while( *files
[idx
+1] ) {
4593 fstrcpy( files
[idx
], files
[idx
+1] );
4602 /**********************************************************************
4603 Check if any of the files used by src are also used by drv
4604 *********************************************************************/
4606 static BOOL
trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*src
,
4607 NT_PRINTER_DRIVER_INFO_LEVEL_3
*drv
)
4609 BOOL in_use
= False
;
4615 /* check each file. Remove it from the src structure if it overlaps */
4617 if ( drv_file_in_use(src
->driverpath
, drv
) ) {
4619 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driverpath
));
4620 fstrcpy( src
->driverpath
, "" );
4623 if ( drv_file_in_use(src
->datafile
, drv
) ) {
4625 DEBUG(10,("Removing datafile [%s] from list\n", src
->datafile
));
4626 fstrcpy( src
->datafile
, "" );
4629 if ( drv_file_in_use(src
->configfile
, drv
) ) {
4631 DEBUG(10,("Removing configfile [%s] from list\n", src
->configfile
));
4632 fstrcpy( src
->configfile
, "" );
4635 if ( drv_file_in_use(src
->helpfile
, drv
) ) {
4637 DEBUG(10,("Removing helpfile [%s] from list\n", src
->helpfile
));
4638 fstrcpy( src
->helpfile
, "" );
4641 /* are there any dependentfiles to examine? */
4643 if ( !src
->dependentfiles
)
4646 while ( *src
->dependentfiles
[i
] ) {
4647 if ( drv_file_in_use(src
->dependentfiles
[i
], drv
) ) {
4649 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependentfiles
[i
]));
4650 trim_dependent_file( src
->dependentfiles
, i
);
4658 /****************************************************************************
4659 Determine whether or not a particular driver files are currently being
4660 used by any other driver.
4662 Return value is True if any files were in use by other drivers
4663 and False otherwise.
4665 Upon return, *info has been modified to only contain the driver files
4666 which are not in use
4667 ****************************************************************************/
4669 BOOL
printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info
)
4674 fstring
*list
= NULL
;
4675 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4680 version
= info
->cversion
;
4682 /* loop over all driver versions */
4684 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4686 /* get the list of drivers */
4689 ndrivers
= get_ntdrivers(&list
, info
->environment
, version
);
4691 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4692 ndrivers
, info
->environment
, version
));
4694 /* check each driver for overlap in files */
4696 for (i
=0; i
<ndrivers
; i
++) {
4697 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4699 ZERO_STRUCT(driver
);
4701 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, list
[i
], info
->environment
, version
)) ) {
4706 /* check if d2 uses any files from d1 */
4707 /* only if this is a different driver than the one being deleted */
4709 if ( !strequal(info
->name
, driver
.info_3
->name
) ) {
4710 if ( trim_overlap_drv_files(info
, driver
.info_3
) ) {
4711 free_a_printer_driver(driver
, 3);
4717 free_a_printer_driver(driver
, 3);
4722 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4724 driver
.info_3
= info
;
4726 if ( DEBUGLEVEL
>= 20 )
4727 dump_a_printer_driver( driver
, 3 );
4732 /****************************************************************************
4733 Actually delete the driver files. Make sure that
4734 printer_driver_files_in_use() return False before calling
4736 ****************************************************************************/
4738 static BOOL
delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
)
4743 connection_struct
*conn
;
4753 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3
->name
, info_3
->cversion
));
4756 * Connect to the print$ share under the same account as the
4757 * user connected to the rpc pipe. Note we must be root to
4761 null_pw
= data_blob( NULL
, 0 );
4762 fstrcpy(res_type
, "A:");
4764 conn
= make_connection_with_chdir( "print$", null_pw
, res_type
, user
->vuid
, &nt_status
);
4768 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4772 /* Save who we are - we are temporarily becoming the connection user. */
4774 if ( !become_user(conn
, conn
->vuid
) ) {
4775 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4779 /* now delete the files; must strip the '\print$' string from
4782 if ( *info_3
->driverpath
) {
4783 if ( (s
= strchr( &info_3
->driverpath
[1], '\\' )) != NULL
) {
4785 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4786 DEBUG(10,("deleting driverfile [%s]\n", s
));
4787 unlink_internals(conn
, 0, file
);
4791 if ( *info_3
->configfile
) {
4792 if ( (s
= strchr( &info_3
->configfile
[1], '\\' )) != NULL
) {
4794 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4795 DEBUG(10,("deleting configfile [%s]\n", s
));
4796 unlink_internals(conn
, 0, file
);
4800 if ( *info_3
->datafile
) {
4801 if ( (s
= strchr( &info_3
->datafile
[1], '\\' )) != NULL
) {
4803 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4804 DEBUG(10,("deleting datafile [%s]\n", s
));
4805 unlink_internals(conn
, 0, file
);
4809 if ( *info_3
->helpfile
) {
4810 if ( (s
= strchr( &info_3
->helpfile
[1], '\\' )) != NULL
) {
4812 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4813 DEBUG(10,("deleting helpfile [%s]\n", s
));
4814 unlink_internals(conn
, 0, file
);
4818 /* check if we are done removing files */
4820 if ( info_3
->dependentfiles
) {
4821 while ( info_3
->dependentfiles
[i
][0] ) {
4824 /* bypass the "\print$" portion of the path */
4826 if ( (p
= strchr( info_3
->dependentfiles
[i
]+1, '\\' )) != NULL
) {
4828 driver_unix_convert(file
, conn
, NULL
, &bad_path
, &st
);
4829 DEBUG(10,("deleting dependent file [%s]\n", file
));
4830 unlink_internals(conn
, 0, file
);
4842 /****************************************************************************
4843 Remove a printer driver from the TDB. This assumes that the the driver was
4844 previously looked up.
4845 ***************************************************************************/
4847 WERROR
delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3
*info_3
, struct current_user
*user
,
4848 uint32 version
, BOOL delete_files
)
4852 TDB_DATA kbuf
, dbuf
;
4853 NT_PRINTER_DRIVER_INFO_LEVEL ctr
;
4855 /* delete the tdb data first */
4857 arch
= get_short_archi(info_3
->environment
);
4858 slprintf(key
, sizeof(key
)-1, "%s%s/%d/%s", DRIVERS_PREFIX
,
4859 arch
, version
, info_3
->name
);
4861 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4862 key
, delete_files
? "TRUE" : "FALSE" ));
4864 ctr
.info_3
= info_3
;
4865 dump_a_printer_driver( ctr
, 3 );
4868 kbuf
.dsize
=strlen(key
)+1;
4870 /* check if the driver actually exists for this environment */
4872 dbuf
= tdb_fetch( tdb_drivers
, kbuf
);
4874 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
4875 return WERR_UNKNOWN_PRINTER_DRIVER
;
4878 SAFE_FREE( dbuf
.dptr
);
4880 /* ok... the driver exists so the delete should return success */
4882 if (tdb_delete(tdb_drivers
, kbuf
) == -1) {
4883 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
4884 return WERR_ACCESS_DENIED
;
4888 * now delete any associated files if delete_files == True
4889 * even if this part failes, we return succes because the
4890 * driver doesn not exist any more
4894 delete_driver_files( info_3
, user
);
4897 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
4902 /****************************************************************************
4903 Store a security desc for a printer.
4904 ****************************************************************************/
4906 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
4908 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
4909 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
4911 TALLOC_CTX
*mem_ctx
= NULL
;
4915 mem_ctx
= talloc_init("nt_printing_setsec");
4916 if (mem_ctx
== NULL
)
4919 /* The old owner and group sids of the security descriptor are not
4920 present when new ACEs are added or removed by changing printer
4921 permissions through NT. If they are NULL in the new security
4922 descriptor then copy them over from the old one. */
4924 if (!secdesc_ctr
->sec
->owner_sid
|| !secdesc_ctr
->sec
->grp_sid
) {
4925 DOM_SID
*owner_sid
, *group_sid
;
4926 SEC_ACL
*dacl
, *sacl
;
4927 SEC_DESC
*psd
= NULL
;
4930 nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
);
4932 /* Pick out correct owner and group sids */
4934 owner_sid
= secdesc_ctr
->sec
->owner_sid
?
4935 secdesc_ctr
->sec
->owner_sid
:
4936 old_secdesc_ctr
->sec
->owner_sid
;
4938 group_sid
= secdesc_ctr
->sec
->grp_sid
?
4939 secdesc_ctr
->sec
->grp_sid
:
4940 old_secdesc_ctr
->sec
->grp_sid
;
4942 dacl
= secdesc_ctr
->sec
->dacl
?
4943 secdesc_ctr
->sec
->dacl
:
4944 old_secdesc_ctr
->sec
->dacl
;
4946 sacl
= secdesc_ctr
->sec
->sacl
?
4947 secdesc_ctr
->sec
->sacl
:
4948 old_secdesc_ctr
->sec
->sacl
;
4950 /* Make a deep copy of the security descriptor */
4952 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sec
->revision
, secdesc_ctr
->sec
->type
,
4953 owner_sid
, group_sid
,
4958 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
4961 if (!new_secdesc_ctr
) {
4962 new_secdesc_ctr
= secdesc_ctr
;
4965 /* Store the security descriptor in a tdb */
4967 prs_init(&ps
, (uint32
)sec_desc_size(new_secdesc_ctr
->sec
) +
4968 sizeof(SEC_DESC_BUF
), mem_ctx
, MARSHALL
);
4970 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr
,
4972 status
= WERR_BADFUNC
;
4976 key
= make_printers_secdesc_tdbkey( sharename
);
4978 if (tdb_prs_store(tdb_printers
, key
, &ps
)==0) {
4981 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
4982 status
= WERR_BADFUNC
;
4985 /* Free malloc'ed memory */
4991 talloc_destroy(mem_ctx
);
4995 /****************************************************************************
4996 Construct a default security descriptor buffer for a printer.
4997 ****************************************************************************/
4999 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5001 SEC_ACE ace
[5]; /* max number of ace entries */
5004 SEC_ACL
*psa
= NULL
;
5005 SEC_DESC_BUF
*sdb
= NULL
;
5006 SEC_DESC
*psd
= NULL
;
5010 /* Create an ACE where Everyone is allowed to print */
5012 init_sec_access(&sa
, PRINTER_ACE_PRINT
);
5013 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5014 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5016 /* Add the domain admins group if we are a DC */
5019 DOM_SID domadmins_sid
;
5021 sid_copy(&domadmins_sid
, get_global_sam_sid());
5022 sid_append_rid(&domadmins_sid
, DOMAIN_GROUP_RID_ADMINS
);
5024 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5025 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5026 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5027 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5028 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5029 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5031 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5032 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5034 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5035 init_sec_ace(&ace
[i
++], &adm_sid
,
5036 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5037 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5038 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5039 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5042 /* add BUILTIN\Administrators as FULL CONTROL */
5044 init_sec_access(&sa
, PRINTER_ACE_FULL_CONTROL
);
5045 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5046 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5047 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5048 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5049 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5050 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5052 /* Make the security descriptor owned by the BUILTIN\Administrators */
5054 /* The ACL revision number in rpc_secdesc.h differs from the one
5055 created by NT when setting ACE entries in printer
5056 descriptors. NT4 complains about the property being edited by a
5059 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5060 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5061 &global_sid_Builtin_Administrators
,
5062 &global_sid_Builtin_Administrators
,
5063 NULL
, psa
, &sd_size
);
5067 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5071 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5073 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5074 (unsigned int)sd_size
));
5079 /****************************************************************************
5080 Get a security desc for a printer.
5081 ****************************************************************************/
5083 BOOL
nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5089 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5090 sharename
= temp
+ 1;
5093 /* Fetch security descriptor from tdb */
5095 key
= make_printers_secdesc_tdbkey( sharename
);
5097 if (tdb_prs_fetch(tdb_printers
, key
, &ps
, ctx
)!=0 ||
5098 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1)) {
5100 DEBUG(4,("using default secdesc for %s\n", sharename
));
5102 if (!(*secdesc_ctr
= construct_default_printer_sdb(ctx
))) {
5106 /* Save default security descriptor for later */
5108 prs_init(&ps
, (uint32
)sec_desc_size((*secdesc_ctr
)->sec
) +
5109 sizeof(SEC_DESC_BUF
), ctx
, MARSHALL
);
5111 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr
, &ps
, 1))
5112 tdb_prs_store(tdb_printers
, key
, &ps
);
5119 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5120 this security descriptor has been created when winbindd was
5121 down. Take ownership of security descriptor. */
5123 if (sid_equal((*secdesc_ctr
)->sec
->owner_sid
, &global_sid_World
)) {
5126 /* Change sd owner to workgroup administrator */
5128 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5129 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5130 SEC_DESC
*psd
= NULL
;
5135 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5137 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sec
->revision
, (*secdesc_ctr
)->sec
->type
,
5139 (*secdesc_ctr
)->sec
->grp_sid
,
5140 (*secdesc_ctr
)->sec
->sacl
,
5141 (*secdesc_ctr
)->sec
->dacl
,
5144 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5146 /* Swap with other one */
5148 *secdesc_ctr
= new_secdesc_ctr
;
5152 nt_printing_setsec(sharename
, *secdesc_ctr
);
5156 if (DEBUGLEVEL
>= 10) {
5157 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sec
->dacl
;
5160 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5161 sharename
, the_acl
->num_aces
));
5163 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5166 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5168 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str
,
5169 the_acl
->ace
[i
].type
, the_acl
->ace
[i
].flags
,
5170 the_acl
->ace
[i
].info
.mask
));
5180 1: level not implemented
5181 2: file doesn't exist
5182 3: can't allocate memory
5183 4: can't free memory
5184 5: non existant struct
5188 A printer and a printer driver are 2 different things.
5189 NT manages them separatelly, Samba does the same.
5190 Why ? Simply because it's easier and it makes sense !
5192 Now explanation: You have 3 printers behind your samba server,
5193 2 of them are the same make and model (laser A and B). But laser B
5194 has an 3000 sheet feeder and laser A doesn't such an option.
5195 Your third printer is an old dot-matrix model for the accounting :-).
5197 If the /usr/local/samba/lib directory (default dir), you will have
5198 5 files to describe all of this.
5200 3 files for the printers (1 by printer):
5203 NTprinter_accounting
5204 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5205 NTdriver_printer model X
5206 NTdriver_printer model Y
5208 jfm: I should use this comment for the text file to explain
5209 same thing for the forms BTW.
5210 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5214 /* Convert generic access rights to printer object specific access rights.
5215 It turns out that NT4 security descriptors use generic access rights and
5216 NT5 the object specific ones. */
5218 void map_printer_permissions(SEC_DESC
*sd
)
5222 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5223 se_map_generic(&sd
->dacl
->ace
[i
].info
.mask
,
5224 &printer_generic_mapping
);
5228 /****************************************************************************
5229 Check a user has permissions to perform the given operation. We use the
5230 permission constants defined in include/rpc_spoolss.h to check the various
5231 actions we perform when checking printer access.
5233 PRINTER_ACCESS_ADMINISTER:
5234 print_queue_pause, print_queue_resume, update_printer_sec,
5235 update_printer, spoolss_addprinterex_level_2,
5236 _spoolss_setprinterdata
5241 JOB_ACCESS_ADMINISTER:
5242 print_job_delete, print_job_pause, print_job_resume,
5245 Try access control in the following order (for performance reasons):
5246 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5247 2) check security descriptor (bit comparisons in memory)
5248 3) "printer admins" (may result in numerous calls to winbind)
5250 ****************************************************************************/
5251 BOOL
print_access_check(struct current_user
*user
, int snum
, int access_type
)
5253 SEC_DESC_BUF
*secdesc
= NULL
;
5254 uint32 access_granted
;
5258 TALLOC_CTX
*mem_ctx
= NULL
;
5259 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5261 /* If user is NULL then use the current_user structure */
5264 user
= ¤t_user
;
5266 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5268 if ( user
->uid
== 0 || user_has_privileges(user
->nt_user_token
, &se_printop
) ) {
5272 /* Get printer name */
5274 pname
= PRINTERNAME(snum
);
5276 if (!pname
|| !*pname
) {
5281 /* Get printer security descriptor */
5283 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5288 nt_printing_getsec(mem_ctx
, pname
, &secdesc
);
5290 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5291 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5293 /* Create a child security descriptor to check permissions
5294 against. This is because print jobs are child objects
5295 objects of a printer. */
5297 secdesc
= se_create_child_secdesc(mem_ctx
, parent_secdesc
->sec
, False
);
5299 /* Now this is the bit that really confuses me. The access
5300 type needs to be changed from JOB_ACCESS_ADMINISTER to
5301 PRINTER_ACCESS_ADMINISTER for this to work. Something
5302 to do with the child (job) object becoming like a
5305 access_type
= PRINTER_ACCESS_ADMINISTER
;
5310 map_printer_permissions(secdesc
->sec
);
5312 result
= se_access_check(secdesc
->sec
, user
->nt_user_token
, access_type
,
5313 &access_granted
, &status
);
5315 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
5317 /* see if we need to try the printer admin list */
5319 if ( access_granted
== 0 ) {
5320 if ( user_in_list(uidtoname(user
->uid
), lp_printer_admin(snum
), user
->groups
, user
->ngroups
) )
5324 talloc_destroy(mem_ctx
);
5332 /****************************************************************************
5333 Check the time parameters allow a print operation.
5334 *****************************************************************************/
5336 BOOL
print_time_access_check(int snum
)
5338 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5340 time_t now
= time(NULL
);
5344 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))))
5347 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5351 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5353 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5356 free_a_printer(&printer
, 2);
5364 /****************************************************************************
5365 Fill in the servername sent in the _spoolss_open_printer_ex() call
5366 ****************************************************************************/
5368 char* get_server_name( Printer_entry
*printer
)
5370 return printer
->servername
;