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 3 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, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
26 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
27 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
28 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43 /* Map generic permissions to printer object specific permissions */
45 const struct generic_mapping printer_generic_mapping
= {
52 const struct standard_mapping printer_std_mapping
= {
59 /* Map generic permissions to print server object specific permissions */
61 const struct generic_mapping printserver_generic_mapping
= {
68 const struct generic_mapping printserver_std_mapping
= {
75 /* Map generic permissions to job object specific permissions */
77 const struct generic_mapping job_generic_mapping
= {
84 /* We need one default form to support our default printer. Msoft adds the
85 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
86 array index). Letter is always first, so (for the current code) additions
87 always put things in the correct order. */
88 static const nt_forms_struct default_forms
[] = {
89 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
92 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
93 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
94 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
95 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
96 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
97 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
99 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
100 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
101 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
102 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
103 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
104 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
105 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
106 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
108 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
109 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
110 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
111 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
112 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
113 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
114 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
115 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
116 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
117 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
118 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
119 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
120 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
121 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
123 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
124 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
125 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
126 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
127 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
128 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
129 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
130 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
131 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
132 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
133 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
134 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
135 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
136 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
138 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
139 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
140 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
141 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
142 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
143 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
144 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
145 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
146 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
147 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
148 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
149 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
150 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
151 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
152 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
153 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
154 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
155 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
156 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
157 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
158 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
159 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
160 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
161 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
162 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
163 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
164 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
165 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
166 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
167 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
168 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
169 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
170 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
171 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
172 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
173 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
174 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
175 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
176 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
177 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
178 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
179 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
180 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
181 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
182 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
183 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
184 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
185 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
186 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
187 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
188 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
189 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
190 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
191 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
192 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
193 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
194 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
195 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
196 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
197 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
198 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
199 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
200 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
201 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
202 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
203 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
204 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
205 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
206 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
209 static const struct print_architecture_table_node archi_table
[]= {
211 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
212 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
213 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
214 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
215 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
216 {"Windows IA64", SPL_ARCH_IA64
, 3 },
217 {"Windows x64", SPL_ARCH_X64
, 3 },
222 /****************************************************************************
223 generate a new TDB_DATA key for storing a printer
224 ****************************************************************************/
226 static TDB_DATA
make_printer_tdbkey(TALLOC_CTX
*ctx
, const char *sharename
)
232 fstrcpy(share
, sharename
);
235 keystr
= talloc_asprintf(ctx
, "%s%s", PRINTERS_PREFIX
, share
);
236 key
= string_term_tdb_data(keystr
? keystr
: "");
241 /****************************************************************************
242 generate a new TDB_DATA key for storing a printer security descriptor
243 ****************************************************************************/
245 static TDB_DATA
make_printers_secdesc_tdbkey(TALLOC_CTX
*ctx
,
246 const char* sharename
)
252 fstrcpy(share
, sharename
);
255 keystr
= talloc_asprintf(ctx
, "%s%s", SECDESC_PREFIX
, share
);
256 key
= string_term_tdb_data(keystr
? keystr
: "");
261 /****************************************************************************
262 ****************************************************************************/
264 static bool upgrade_to_version_3(void)
266 TDB_DATA kbuf
, newkey
, dbuf
;
268 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
270 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
271 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
273 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
275 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
276 DEBUG(0,("upgrade_to_version_3:moving form\n"));
277 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
278 SAFE_FREE(dbuf
.dptr
);
279 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
282 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
283 SAFE_FREE(dbuf
.dptr
);
284 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
289 if (strncmp((const char *)kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
290 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
291 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
292 SAFE_FREE(dbuf
.dptr
);
293 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
296 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
297 SAFE_FREE(dbuf
.dptr
);
298 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
303 if (strncmp((const char *)kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
304 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
305 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
306 SAFE_FREE(dbuf
.dptr
);
307 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
310 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
311 SAFE_FREE(dbuf
.dptr
);
312 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
317 SAFE_FREE(dbuf
.dptr
);
323 /*******************************************************************
324 Fix an issue with security descriptors. Printer sec_desc must
325 use more than the generic bits that were previously used
326 in <= 3.0.14a. They must also have a owner and group SID assigned.
327 Otherwise, any printers than have been migrated to a Windows
328 host using printmig.exe will not be accessible.
329 *******************************************************************/
331 static int sec_desc_upg_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
332 TDB_DATA data
, void *state
)
335 SEC_DESC_BUF
*sd_orig
= NULL
;
336 SEC_DESC_BUF
*sd_new
, *sd_store
;
337 SEC_DESC
*sec
, *new_sec
;
338 TALLOC_CTX
*ctx
= state
;
343 if (!data
.dptr
|| data
.dsize
== 0) {
347 if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 ) {
351 /* upgrade the security descriptor */
353 status
= unmarshall_sec_desc_buf(ctx
, data
.dptr
, data
.dsize
, &sd_orig
);
354 if (!NT_STATUS_IS_OK(status
)) {
355 /* delete bad entries */
356 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
357 (const char *)key
.dptr
));
358 tdb_delete( tdb_printers
, key
);
367 /* is this even valid? */
373 /* update access masks */
375 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
376 switch ( sec
->dacl
->aces
[i
].access_mask
) {
377 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
378 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_PRINT
;
381 case GENERIC_ALL_ACCESS
:
382 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_FULL_CONTROL
;
385 case READ_CONTROL_ACCESS
:
386 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
388 default: /* no change */
393 /* create a new SEC_DESC with the appropriate owner and group SIDs */
395 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
396 &global_sid_Builtin_Administrators
,
397 &global_sid_Builtin_Administrators
,
398 NULL
, NULL
, &size_new_sec
);
402 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
407 if ( !(sd_store
= sec_desc_merge_buf( ctx
, sd_new
, sd_orig
)) ) {
408 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
414 sd_size
= ndr_size_security_descriptor(sd_store
->sd
, NULL
, 0)
415 + sizeof(SEC_DESC_BUF
);
417 status
= marshall_sec_desc_buf(ctx
, sd_store
, &data
.dptr
, &data
.dsize
);
418 if (!NT_STATUS_IS_OK(status
)) {
419 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
423 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
)
461 TALLOC_CTX
*ctx
= talloc_tos();
464 if (!data
.dptr
|| data
.dsize
== 0)
467 /* upgrade printer records and security descriptors */
469 if ( strncmp((const char *) key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
470 new_key
= make_printer_tdbkey(ctx
, (const char *)key
.dptr
+strlen(PRINTERS_PREFIX
) );
472 else if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
473 new_key
= make_printers_secdesc_tdbkey(ctx
, (const char *)key
.dptr
+strlen(SECDESC_PREFIX
) );
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(struct messaging_context
*msg_ctx
)
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(state_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 state_path("ntdrivers.tdb"), strerror(errno
) ));
540 tdb_close(tdb_printers
);
541 tdb_printers
= tdb_open_log(state_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 state_path("ntprinters.tdb"), strerror(errno
) ));
549 tdb_close(tdb_forms
);
550 tdb_forms
= tdb_open_log(state_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 state_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 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
611 do_drv_upgrade_printer
);
614 * register callback to handle updating printer data
615 * when a driver is initialized
618 messaging_register(msg_ctx
, NULL
, MSG_PRINTERDATA_INIT_RESET
,
619 reset_all_printerdata
);
621 /* of course, none of the message callbacks matter if you don't
622 tell messages.c that you interested in receiving PRINT_GENERAL
623 msgs. This is done in serverid_register() */
626 if ( lp_security() == SEC_ADS
) {
627 win_rc
= check_published_printers();
628 if (!W_ERROR_IS_OK(win_rc
))
629 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
635 /*******************************************************************
636 Function to allow filename parsing "the old way".
637 ********************************************************************/
639 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
640 const char *old_name
,
641 struct smb_filename
**smb_fname
)
644 TALLOC_CTX
*ctx
= talloc_tos();
645 char *name
= talloc_strdup(ctx
, old_name
);
648 return NT_STATUS_NO_MEMORY
;
651 name
= unix_clean_name(ctx
, name
);
653 return NT_STATUS_NO_MEMORY
;
655 trim_string(name
,"/","/");
657 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
658 if (!NT_STATUS_IS_OK(status
)) {
659 return NT_STATUS_NO_MEMORY
;
665 /*******************************************************************
666 tdb traversal function for counting printers.
667 ********************************************************************/
669 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
670 TDB_DATA data
, void *context
)
672 int *printer_count
= (int*)context
;
674 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
676 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
682 /*******************************************************************
683 Update the spooler global c_setprinter. This variable is initialized
684 when the parent smbd starts with the number of existing printers. It
685 is monotonically increased by the current number of printers *after*
686 each add or delete printer RPC. Only Microsoft knows why... JRR020119
687 ********************************************************************/
689 uint32
update_c_setprinter(bool initialize
)
692 int32 printer_count
= 0;
694 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
696 /* Traverse the tdb, counting the printers */
697 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
699 /* If initializing, set c_setprinter to current printers count
700 * otherwise, bump it by the current printer count
703 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
705 c_setprinter
= printer_count
;
707 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
708 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
710 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
712 return (uint32
)c_setprinter
;
715 /*******************************************************************
716 Get the spooler global c_setprinter, accounting for initialization.
717 ********************************************************************/
719 uint32
get_c_setprinter(void)
721 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
723 if (c_setprinter
== (int32
)-1)
724 c_setprinter
= update_c_setprinter(True
);
726 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
728 return (uint32
)c_setprinter
;
731 /****************************************************************************
732 Get builtin form struct list.
733 ****************************************************************************/
735 int get_builtin_ntforms(nt_forms_struct
**list
)
737 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
741 return ARRAY_SIZE(default_forms
);
744 /****************************************************************************
745 get a builtin form struct
746 ****************************************************************************/
748 bool get_a_builtin_ntform_by_string(const char *form_name
, nt_forms_struct
*form
)
751 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
752 for (i
=0; i
<ARRAY_SIZE(default_forms
); i
++) {
753 if (strequal(form_name
,default_forms
[i
].name
)) {
754 DEBUGADD(6,("Found builtin form %s \n", form_name
));
755 memcpy(form
,&default_forms
[i
],sizeof(*form
));
763 /****************************************************************************
764 get a form struct list.
765 ****************************************************************************/
767 int get_ntforms(nt_forms_struct
**list
)
769 TDB_DATA kbuf
, newkey
, dbuf
;
770 nt_forms_struct form
;
777 for (kbuf
= tdb_firstkey(tdb_forms
);
779 newkey
= tdb_nextkey(tdb_forms
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
)
781 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
784 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
788 fstrcpy(form
.name
, (const char *)kbuf
.dptr
+strlen(FORMS_PREFIX
));
789 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
790 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
791 &form
.top
, &form
.right
, &form
.bottom
);
792 SAFE_FREE(dbuf
.dptr
);
793 if (ret
!= dbuf
.dsize
)
796 *list
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
798 DEBUG(0,("get_ntforms: Realloc fail.\n"));
809 /****************************************************************************
810 write a form struct list
811 ****************************************************************************/
813 int write_ntforms(nt_forms_struct
**list
, int number
)
815 TALLOC_CTX
*ctx
= talloc_tos();
822 for (i
=0;i
<number
;i
++) {
823 /* save index, so list is rebuilt in correct order */
824 len
= tdb_pack(NULL
, 0, "dddddddd",
825 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
826 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
831 buf
= TALLOC_ARRAY(ctx
, char, len
);
835 len
= tdb_pack((uint8
*)buf
, len
, "dddddddd",
836 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
837 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
839 key
= talloc_asprintf(ctx
, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
844 dbuf
.dptr
= (uint8
*)buf
;
845 if (tdb_store_bystring(tdb_forms
, key
, dbuf
, TDB_REPLACE
) != 0) {
857 /****************************************************************************
858 add a form struct at the end of the list
859 ****************************************************************************/
860 bool add_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int *count
)
866 * NT tries to add forms even when
867 * they are already in the base
868 * only update the values if already present
873 for (n
=0; n
<*count
; n
++) {
874 if ( strequal((*list
)[n
].name
, form
->form_name
) ) {
881 if((*list
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
882 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
885 fstrcpy((*list
)[n
].name
, form
->form_name
);
889 (*list
)[n
].flag
= form
->flags
;
890 (*list
)[n
].width
= form
->size
.width
;
891 (*list
)[n
].length
= form
->size
.height
;
892 (*list
)[n
].left
= form
->area
.left
;
893 (*list
)[n
].top
= form
->area
.top
;
894 (*list
)[n
].right
= form
->area
.right
;
895 (*list
)[n
].bottom
= form
->area
.bottom
;
897 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
898 update
? "updated" : "added", form
->form_name
));
903 /****************************************************************************
904 Delete a named form struct.
905 ****************************************************************************/
907 bool delete_a_form(nt_forms_struct
**list
, const char *del_name
, int *count
, WERROR
*ret
)
914 for (n
=0; n
<*count
; n
++) {
915 if (!strncmp((*list
)[n
].name
, del_name
, strlen(del_name
))) {
916 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name
));
922 DEBUG(10,("delete_a_form, [%s] not found\n", del_name
));
923 *ret
= WERR_INVALID_FORM_NAME
;
927 if (asprintf(&key
, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
) < 0) {
931 if (tdb_delete_bystring(tdb_forms
, key
) != 0) {
940 /****************************************************************************
941 Update a form struct.
942 ****************************************************************************/
944 void update_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int count
)
948 DEBUG(106, ("[%s]\n", form
->form_name
));
949 for (n
=0; n
<count
; n
++) {
950 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
951 if (!strncmp((*list
)[n
].name
, form
->form_name
, strlen(form
->form_name
)))
955 if (n
==count
) return;
957 (*list
)[n
].flag
= form
->flags
;
958 (*list
)[n
].width
= form
->size
.width
;
959 (*list
)[n
].length
= form
->size
.height
;
960 (*list
)[n
].left
= form
->area
.left
;
961 (*list
)[n
].top
= form
->area
.top
;
962 (*list
)[n
].right
= form
->area
.right
;
963 (*list
)[n
].bottom
= form
->area
.bottom
;
966 /****************************************************************************
967 Get the nt drivers list.
968 Traverse the database and look-up the matching names.
969 ****************************************************************************/
970 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
973 const char *short_archi
;
975 TDB_DATA kbuf
, newkey
;
977 short_archi
= get_short_archi(architecture
);
982 if (asprintf(&key
, "%s%s/%d/", DRIVERS_PREFIX
,
983 short_archi
, version
) < 0) {
987 for (kbuf
= tdb_firstkey(tdb_drivers
);
989 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
991 if (strncmp((const char *)kbuf
.dptr
, key
, strlen(key
)) != 0)
994 if((*list
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
995 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1000 fstrcpy((*list
)[total
], (const char *)kbuf
.dptr
+strlen(key
));
1008 /****************************************************************************
1009 Function to do the mapping between the long architecture name and
1011 ****************************************************************************/
1013 const char *get_short_archi(const char *long_archi
)
1017 DEBUG(107,("Getting architecture dependant directory\n"));
1020 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
1021 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
1023 if (archi_table
[i
].long_archi
==NULL
) {
1024 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
1028 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1030 DEBUGADD(108,("index: [%d]\n", i
));
1031 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
1032 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
1034 return archi_table
[i
].short_archi
;
1037 /****************************************************************************
1038 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1039 There are two case to be covered here: PE (Portable Executable) and NE (New
1040 Executable) files. Both files support the same INFO structure, but PE files
1041 store the signature in unicode, and NE files store it as !unicode.
1042 returns -1 on error, 1 on version info found, and 0 on no version info found.
1043 ****************************************************************************/
1045 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1051 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
1052 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1053 fname
, DOS_HEADER_SIZE
));
1057 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1058 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1059 fname
, (unsigned long)byte_count
));
1060 goto no_version_info
;
1063 /* Is this really a DOS header? */
1064 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1065 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1066 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1067 goto no_version_info
;
1070 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1071 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1072 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1074 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1075 goto no_version_info
;
1078 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1079 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
1080 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1081 fname
, (unsigned long)byte_count
));
1082 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1083 goto no_version_info
;
1086 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1087 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1088 unsigned int num_sections
;
1089 unsigned int section_table_bytes
;
1091 /* Just skip over optional header to get to section table */
1092 if (SMB_VFS_LSEEK(fsp
,
1093 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
1094 SEEK_CUR
) == (SMB_OFF_T
)-1) {
1095 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1100 /* get the section table */
1101 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1102 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1103 if (section_table_bytes
== 0)
1107 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
1108 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1109 fname
, section_table_bytes
));
1113 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1114 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1115 fname
, (unsigned long)byte_count
));
1119 /* Iterate the section table looking for the resource section ".rsrc" */
1120 for (i
= 0; i
< num_sections
; i
++) {
1121 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1123 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1124 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1125 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1127 if (section_bytes
== 0)
1131 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
1132 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1133 fname
, section_bytes
));
1137 /* Seek to the start of the .rsrc section info */
1138 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1139 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1144 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1145 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1146 fname
, (unsigned long)byte_count
));
1150 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1153 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1154 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1155 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1156 /* Align to next long address */
1157 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1159 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1160 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1161 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1163 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1164 fname
, *major
, *minor
,
1165 (*major
>>16)&0xffff, *major
&0xffff,
1166 (*minor
>>16)&0xffff, *minor
&0xffff));
1175 /* Version info not found, fall back to origin date/time */
1176 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1180 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1181 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1182 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1183 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1184 /* At this point, we assume the file is in error. It still could be somthing
1185 * else besides a NE file, but it unlikely at this point. */
1189 /* Allocate a bit more space to speed up things */
1191 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1192 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1193 fname
, PE_HEADER_SIZE
));
1197 /* This is a HACK! I got tired of trying to sort through the messy
1198 * 'NE' file format. If anyone wants to clean this up please have at
1199 * it, but this works. 'NE' files will eventually fade away. JRR */
1200 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1201 /* Cover case that should not occur in a well formed 'NE' .dll file */
1202 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1204 for(i
=0; i
<byte_count
; i
++) {
1205 /* Fast skip past data that can't possibly match */
1206 if (buf
[i
] != 'V') continue;
1208 /* Potential match data crosses buf boundry, move it to beginning
1209 * of buf, and fill the buf with as much as it will hold. */
1210 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1213 memcpy(buf
, &buf
[i
], byte_count
-i
);
1214 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1215 (byte_count
-i
))) < 0) {
1217 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1222 byte_count
= bc
+ (byte_count
- i
);
1223 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1228 /* Check that the full signature string and the magic number that
1229 * follows exist (not a perfect solution, but the chances that this
1230 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1231 * twice, as it is simpler to read the code. */
1232 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1233 /* Compute skip alignment to next long address */
1234 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
1235 sizeof(VS_SIGNATURE
)) & 3;
1236 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1238 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1239 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1240 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1241 fname
, *major
, *minor
,
1242 (*major
>>16)&0xffff, *major
&0xffff,
1243 (*minor
>>16)&0xffff, *minor
&0xffff));
1250 /* Version info not found, fall back to origin date/time */
1251 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1256 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1257 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1258 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1269 /****************************************************************************
1270 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1271 share one or more files. During the MS installation process files are checked
1272 to insure that only a newer version of a shared file is installed over an
1273 older version. There are several possibilities for this comparison. If there
1274 is no previous version, the new one is newer (obviously). If either file is
1275 missing the version info structure, compare the creation date (on Unix use
1276 the modification date). Otherwise chose the numerically larger version number.
1277 ****************************************************************************/
1279 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1281 bool use_version
= true;
1285 time_t new_create_time
;
1289 time_t old_create_time
;
1291 struct smb_filename
*smb_fname
= NULL
;
1292 files_struct
*fsp
= NULL
;
1298 SET_STAT_INVALID(st
);
1299 new_create_time
= (time_t)0;
1300 old_create_time
= (time_t)0;
1302 /* Get file version info (if available) for previous file (if it exists) */
1303 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
1304 if (!NT_STATUS_IS_OK(status
)) {
1308 status
= SMB_VFS_CREATE_FILE(
1311 0, /* root_dir_fid */
1312 smb_fname
, /* fname */
1313 FILE_GENERIC_READ
, /* access_mask */
1314 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1315 FILE_OPEN
, /* create_disposition*/
1316 0, /* create_options */
1317 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1318 INTERNAL_OPEN_ONLY
, /* oplock_request */
1319 0, /* allocation_size */
1320 0, /* private_flags */
1326 if (!NT_STATUS_IS_OK(status
)) {
1327 /* Old file not found, so by definition new file is in fact newer */
1328 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1329 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
1335 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1341 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1343 use_version
= false;
1344 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1347 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1348 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1349 (long)old_create_time
));
1352 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1355 /* Get file version info (if available) for new file */
1356 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
1357 if (!NT_STATUS_IS_OK(status
)) {
1361 status
= SMB_VFS_CREATE_FILE(
1364 0, /* root_dir_fid */
1365 smb_fname
, /* fname */
1366 FILE_GENERIC_READ
, /* access_mask */
1367 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1368 FILE_OPEN
, /* create_disposition*/
1369 0, /* create_options */
1370 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1371 INTERNAL_OPEN_ONLY
, /* oplock_request */
1372 0, /* allocation_size */
1373 0, /* private_flags */
1379 if (!NT_STATUS_IS_OK(status
)) {
1380 /* New file not found, this shouldn't occur if the caller did its job */
1381 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1382 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
1386 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1392 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1394 use_version
= false;
1395 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1398 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1399 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1400 (long)new_create_time
));
1403 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1406 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1407 /* Compare versions and choose the larger version number */
1408 if (new_major
> old_major
||
1409 (new_major
== old_major
&& new_minor
> old_minor
)) {
1411 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1416 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1422 /* Compare modification time/dates and choose the newest time/date */
1423 if (new_create_time
> old_create_time
) {
1424 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1429 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1437 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1440 TALLOC_FREE(smb_fname
);
1444 /****************************************************************************
1445 Determine the correct cVersion associated with an architecture and driver
1446 ****************************************************************************/
1447 static uint32
get_correct_cversion(struct pipes_struct
*p
,
1448 const char *architecture
,
1449 const char *driverpath_in
,
1454 struct smb_filename
*smb_fname
= NULL
;
1455 char *driverpath
= NULL
;
1456 files_struct
*fsp
= NULL
;
1457 connection_struct
*conn
= NULL
;
1460 fstring printdollar
;
1461 int printdollar_snum
;
1463 *perr
= WERR_INVALID_PARAM
;
1465 /* If architecture is Windows 95/98/ME, the version is always 0. */
1466 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1467 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1472 /* If architecture is Windows x64, the version is always 3. */
1473 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1474 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1479 fstrcpy(printdollar
, "print$");
1481 printdollar_snum
= find_service(printdollar
);
1482 if (printdollar_snum
== -1) {
1483 *perr
= WERR_NO_SUCH_SHARE
;
1487 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1488 lp_pathname(printdollar_snum
),
1489 p
->server_info
, &oldcwd
);
1490 if (!NT_STATUS_IS_OK(nt_status
)) {
1491 DEBUG(0,("get_correct_cversion: create_conn_struct "
1492 "returned %s\n", nt_errstr(nt_status
)));
1493 *perr
= ntstatus_to_werror(nt_status
);
1497 /* Open the driver file (Portable Executable format) and determine the
1498 * deriver the cversion. */
1499 driverpath
= talloc_asprintf(talloc_tos(),
1508 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
1509 if (!NT_STATUS_IS_OK(nt_status
)) {
1510 *perr
= ntstatus_to_werror(nt_status
);
1514 nt_status
= vfs_file_exist(conn
, smb_fname
);
1515 if (!NT_STATUS_IS_OK(nt_status
)) {
1516 *perr
= WERR_BADFILE
;
1520 status
= SMB_VFS_CREATE_FILE(
1523 0, /* root_dir_fid */
1524 smb_fname
, /* fname */
1525 FILE_GENERIC_READ
, /* access_mask */
1526 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1527 FILE_OPEN
, /* create_disposition*/
1528 0, /* create_options */
1529 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1530 INTERNAL_OPEN_ONLY
, /* oplock_request */
1531 0, /* private_flags */
1532 0, /* allocation_size */
1538 if (!NT_STATUS_IS_OK(status
)) {
1539 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1540 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
1541 *perr
= WERR_ACCESS_DENIED
;
1548 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
1549 if (ret
== -1) goto error_exit
;
1552 DEBUG(6,("get_correct_cversion: Version info not "
1554 smb_fname_str_dbg(smb_fname
)));
1559 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1560 * for more details. Version in this case is not just the version of the
1561 * file, but the version in the sense of kernal mode (2) vs. user mode
1562 * (3) drivers. Other bits of the version fields are the version info.
1565 cversion
= major
& 0x0000ffff;
1567 case 2: /* WinNT drivers */
1568 case 3: /* Win2K drivers */
1572 DEBUG(6,("get_correct_cversion: cversion "
1573 "invalid [%s] cversion = %d\n",
1574 smb_fname_str_dbg(smb_fname
),
1579 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1580 " = 0x%x minor = 0x%x\n",
1581 smb_fname_str_dbg(smb_fname
), major
, minor
));
1584 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1585 smb_fname_str_dbg(smb_fname
), cversion
));
1592 TALLOC_FREE(smb_fname
);
1594 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1597 vfs_ChDir(conn
, oldcwd
);
1600 if (cversion
!= -1) {
1606 /****************************************************************************
1607 ****************************************************************************/
1609 #define strip_driver_path(_mem_ctx, _element) do { \
1610 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1611 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1612 W_ERROR_HAVE_NO_MEMORY((_element)); \
1616 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
1617 struct pipes_struct
*rpc_pipe
,
1618 const char *architecture
,
1619 const char **driver_path
,
1620 const char **data_file
,
1621 const char **config_file
,
1622 const char **help_file
,
1623 struct spoolss_StringArray
*dependent_files
,
1626 const char *short_architecture
;
1631 if (!*driver_path
|| !*data_file
|| !*config_file
) {
1632 return WERR_INVALID_PARAM
;
1635 /* clean up the driver name.
1636 * we can get .\driver.dll
1637 * or worse c:\windows\system\driver.dll !
1639 /* using an intermediate string to not have overlaping memcpy()'s */
1641 strip_driver_path(mem_ctx
, *driver_path
);
1642 strip_driver_path(mem_ctx
, *data_file
);
1643 strip_driver_path(mem_ctx
, *config_file
);
1645 strip_driver_path(mem_ctx
, *help_file
);
1648 if (dependent_files
&& dependent_files
->string
) {
1649 for (i
=0; dependent_files
->string
[i
]; i
++) {
1650 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
1654 short_architecture
= get_short_archi(architecture
);
1655 if (!short_architecture
) {
1656 return WERR_UNKNOWN_PRINTER_DRIVER
;
1659 /* jfm:7/16/2000 the client always sends the cversion=0.
1660 * The server should check which version the driver is by reading
1661 * the PE header of driver->driverpath.
1663 * For Windows 95/98 the version is 0 (so the value sent is correct)
1664 * For Windows NT (the architecture doesn't matter)
1665 * NT 3.1: cversion=0
1666 * NT 3.5/3.51: cversion=1
1671 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
1672 *driver_path
, &err
);
1673 if (*version
== -1) {
1680 /****************************************************************************
1681 ****************************************************************************/
1683 WERROR
clean_up_driver_struct(struct pipes_struct
*rpc_pipe
,
1684 struct spoolss_AddDriverInfoCtr
*r
)
1688 return clean_up_driver_struct_level(r
, rpc_pipe
,
1689 r
->info
.info3
->architecture
,
1690 &r
->info
.info3
->driver_path
,
1691 &r
->info
.info3
->data_file
,
1692 &r
->info
.info3
->config_file
,
1693 &r
->info
.info3
->help_file
,
1694 r
->info
.info3
->dependent_files
,
1695 &r
->info
.info3
->version
);
1697 return clean_up_driver_struct_level(r
, rpc_pipe
,
1698 r
->info
.info6
->architecture
,
1699 &r
->info
.info6
->driver_path
,
1700 &r
->info
.info6
->data_file
,
1701 &r
->info
.info6
->config_file
,
1702 &r
->info
.info6
->help_file
,
1703 r
->info
.info6
->dependent_files
,
1704 &r
->info
.info6
->version
);
1706 return WERR_NOT_SUPPORTED
;
1710 /****************************************************************************
1711 This function sucks and should be replaced. JRA.
1712 ****************************************************************************/
1714 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1715 const struct spoolss_AddDriverInfo6
*src
)
1717 dst
->version
= src
->version
;
1719 dst
->driver_name
= src
->driver_name
;
1720 dst
->architecture
= src
->architecture
;
1721 dst
->driver_path
= src
->driver_path
;
1722 dst
->data_file
= src
->data_file
;
1723 dst
->config_file
= src
->config_file
;
1724 dst
->help_file
= src
->help_file
;
1725 dst
->monitor_name
= src
->monitor_name
;
1726 dst
->default_datatype
= src
->default_datatype
;
1727 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1728 dst
->dependent_files
= src
->dependent_files
;
1731 /****************************************************************************
1732 This function sucks and should be replaced. JRA.
1733 ****************************************************************************/
1735 static void convert_level_8_to_level3(TALLOC_CTX
*mem_ctx
,
1736 struct spoolss_AddDriverInfo3
*dst
,
1737 const struct spoolss_DriverInfo8
*src
)
1739 dst
->version
= src
->version
;
1740 dst
->driver_name
= src
->driver_name
;
1741 dst
->architecture
= src
->architecture
;
1742 dst
->driver_path
= src
->driver_path
;
1743 dst
->data_file
= src
->data_file
;
1744 dst
->config_file
= src
->config_file
;
1745 dst
->help_file
= src
->help_file
;
1746 dst
->monitor_name
= src
->monitor_name
;
1747 dst
->default_datatype
= src
->default_datatype
;
1748 if (src
->dependent_files
) {
1749 dst
->dependent_files
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1750 if (!dst
->dependent_files
) return;
1751 dst
->dependent_files
->string
= src
->dependent_files
;
1753 dst
->dependent_files
= NULL
;
1757 /****************************************************************************
1758 ****************************************************************************/
1760 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
1761 connection_struct
*conn
,
1762 const char *driver_file
,
1763 const char *short_architecture
,
1764 uint32_t driver_version
,
1767 struct smb_filename
*smb_fname_old
= NULL
;
1768 struct smb_filename
*smb_fname_new
= NULL
;
1769 char *old_name
= NULL
;
1770 char *new_name
= NULL
;
1774 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
1775 short_architecture
, driver_file
);
1776 W_ERROR_HAVE_NO_MEMORY(old_name
);
1778 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
1779 short_architecture
, driver_version
, driver_file
);
1780 if (new_name
== NULL
) {
1781 TALLOC_FREE(old_name
);
1785 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
1787 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
1788 if (!NT_STATUS_IS_OK(status
)) {
1793 /* Setup a synthetic smb_filename struct */
1794 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
1795 if (!smb_fname_new
) {
1800 smb_fname_new
->base_name
= new_name
;
1802 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1803 "'%s'\n", smb_fname_old
->base_name
,
1804 smb_fname_new
->base_name
));
1806 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
1807 OPENX_FILE_EXISTS_TRUNCATE
|
1808 OPENX_FILE_CREATE_IF_NOT_EXIST
,
1811 if (!NT_STATUS_IS_OK(status
)) {
1812 DEBUG(0,("move_driver_file_to_download_area: Unable "
1813 "to rename [%s] to [%s]: %s\n",
1814 smb_fname_old
->base_name
, new_name
,
1815 nt_errstr(status
)));
1816 ret
= WERR_ACCESS_DENIED
;
1823 TALLOC_FREE(smb_fname_old
);
1824 TALLOC_FREE(smb_fname_new
);
1828 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
1829 struct spoolss_AddDriverInfoCtr
*r
,
1832 struct spoolss_AddDriverInfo3
*driver
;
1833 struct spoolss_AddDriverInfo3 converted_driver
;
1834 const char *short_architecture
;
1835 struct smb_filename
*smb_dname
= NULL
;
1836 char *new_dir
= NULL
;
1837 connection_struct
*conn
= NULL
;
1840 TALLOC_CTX
*ctx
= talloc_tos();
1843 fstring printdollar
;
1844 int printdollar_snum
;
1850 driver
= r
->info
.info3
;
1853 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
1854 driver
= &converted_driver
;
1857 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
1858 return WERR_UNKNOWN_LEVEL
;
1861 short_architecture
= get_short_archi(driver
->architecture
);
1862 if (!short_architecture
) {
1863 return WERR_UNKNOWN_PRINTER_DRIVER
;
1866 fstrcpy(printdollar
, "print$");
1868 printdollar_snum
= find_service(printdollar
);
1869 if (printdollar_snum
== -1) {
1870 *perr
= WERR_NO_SUCH_SHARE
;
1871 return WERR_NO_SUCH_SHARE
;
1874 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1875 lp_pathname(printdollar_snum
),
1876 p
->server_info
, &oldcwd
);
1877 if (!NT_STATUS_IS_OK(nt_status
)) {
1878 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1879 "returned %s\n", nt_errstr(nt_status
)));
1880 *perr
= ntstatus_to_werror(nt_status
);
1884 new_dir
= talloc_asprintf(ctx
,
1892 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1893 if (!NT_STATUS_IS_OK(nt_status
)) {
1898 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1900 create_directory(conn
, NULL
, smb_dname
);
1902 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1903 * listed for this driver which has already been moved, skip it (note:
1904 * drivers may list the same file name several times. Then check if the
1905 * file already exists in archi\version\, if so, check that the version
1906 * info (or time stamps if version info is unavailable) is newer (or the
1907 * date is later). If it is, move it to archi\version\filexxx.yyy.
1908 * Otherwise, delete the file.
1910 * If a file is not moved to archi\version\ because of an error, all the
1911 * rest of the 'unmoved' driver files are removed from archi\. If one or
1912 * more of the driver's files was already moved to archi\version\, it
1913 * potentially leaves the driver in a partially updated state. Version
1914 * trauma will most likely occur if an client attempts to use any printer
1915 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1916 * done is appropriate... later JRR
1919 DEBUG(5,("Moving files now !\n"));
1921 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1923 *perr
= move_driver_file_to_download_area(ctx
,
1925 driver
->driver_path
,
1929 if (!W_ERROR_IS_OK(*perr
)) {
1930 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1937 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1938 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1940 *perr
= move_driver_file_to_download_area(ctx
,
1946 if (!W_ERROR_IS_OK(*perr
)) {
1947 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1955 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1956 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1957 !strequal(driver
->config_file
, driver
->data_file
)) {
1959 *perr
= move_driver_file_to_download_area(ctx
,
1961 driver
->config_file
,
1965 if (!W_ERROR_IS_OK(*perr
)) {
1966 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1974 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1975 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1976 !strequal(driver
->help_file
, driver
->data_file
) &&
1977 !strequal(driver
->help_file
, driver
->config_file
)) {
1979 *perr
= move_driver_file_to_download_area(ctx
,
1985 if (!W_ERROR_IS_OK(*perr
)) {
1986 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1994 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1995 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1996 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1997 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1998 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1999 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
2001 for (j
=0; j
< i
; j
++) {
2002 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
2007 *perr
= move_driver_file_to_download_area(ctx
,
2009 driver
->dependent_files
->string
[i
],
2013 if (!W_ERROR_IS_OK(*perr
)) {
2014 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
2025 TALLOC_FREE(smb_dname
);
2028 vfs_ChDir(conn
, oldcwd
);
2032 if (W_ERROR_EQUAL(*perr
, WERR_OK
)) {
2036 return WERR_UNKNOWN_PRINTER_DRIVER
;
2041 /****************************************************************************
2042 ****************************************************************************/
2044 static uint32
add_a_printer_driver_3(struct spoolss_AddDriverInfo3
*driver
)
2046 TALLOC_CTX
*ctx
= talloc_tos();
2048 const char *architecture
;
2049 char *directory
= NULL
;
2055 architecture
= get_short_archi(driver
->architecture
);
2056 if (!architecture
) {
2060 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2061 * \\server is added in the rpc server layer.
2062 * It does make sense to NOT store the server's name in the printer TDB.
2065 directory
= talloc_asprintf(ctx
, "\\print$\\%s\\%d\\",
2066 architecture
, driver
->version
);
2071 #define gen_full_driver_unc_path(ctx, directory, file) \
2073 if (file && strlen(file)) { \
2074 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2076 file = talloc_strdup(ctx, ""); \
2079 return (uint32_t)-1; \
2083 /* .inf files do not always list a file for each of the four standard files.
2084 * Don't prepend a path to a null filename, or client claims:
2085 * "The server on which the printer resides does not have a suitable
2086 * <printer driver name> printer driver installed. Click OK if you
2087 * wish to install the driver on your local machine."
2090 gen_full_driver_unc_path(ctx
, directory
, driver
->driver_path
);
2091 gen_full_driver_unc_path(ctx
, directory
, driver
->data_file
);
2092 gen_full_driver_unc_path(ctx
, directory
, driver
->config_file
);
2093 gen_full_driver_unc_path(ctx
, directory
, driver
->help_file
);
2095 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
2096 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
2097 gen_full_driver_unc_path(ctx
, directory
,
2098 driver
->dependent_files
->string
[i
]);
2102 key
= talloc_asprintf(ctx
, "%s%s/%d/%s", DRIVERS_PREFIX
,
2103 architecture
, driver
->version
, driver
->driver_name
);
2108 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
2115 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
2117 driver
->driver_name
,
2118 driver
->architecture
,
2119 driver
->driver_path
,
2121 driver
->config_file
,
2123 driver
->monitor_name
? driver
->monitor_name
: "",
2124 driver
->default_datatype
? driver
->default_datatype
: "");
2126 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
2127 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
2128 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
2129 driver
->dependent_files
->string
[i
]);
2133 if (len
!= buflen
) {
2134 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
2136 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2147 ret
= tdb_store_bystring(tdb_drivers
, key
, dbuf
, TDB_REPLACE
);
2151 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
2157 /****************************************************************************
2158 ****************************************************************************/
2160 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8
*driver
)
2162 TALLOC_CTX
*mem_ctx
= talloc_new(talloc_tos());
2163 struct spoolss_AddDriverInfo3 info3
;
2166 convert_level_8_to_level3(mem_ctx
, &info3
, driver
);
2168 ret
= add_a_printer_driver_3(&info3
);
2169 talloc_free(mem_ctx
);
2174 /****************************************************************************
2175 ****************************************************************************/
2177 static WERROR
get_a_printer_driver_3_default(TALLOC_CTX
*mem_ctx
,
2178 struct spoolss_DriverInfo3
*info
,
2179 const char *driver
, const char *arch
)
2181 info
->driver_name
= talloc_strdup(mem_ctx
, driver
);
2182 if (!info
->driver_name
) {
2186 info
->default_datatype
= talloc_strdup(mem_ctx
, "RAW");
2187 if (!info
->default_datatype
) {
2191 info
->driver_path
= talloc_strdup(mem_ctx
, "");
2192 info
->data_file
= talloc_strdup(mem_ctx
, "");
2193 info
->config_file
= talloc_strdup(mem_ctx
, "");
2194 info
->help_file
= talloc_strdup(mem_ctx
, "");
2195 if (!info
->driver_path
|| !info
->data_file
|| !info
->config_file
|| !info
->help_file
) {
2202 /****************************************************************************
2203 ****************************************************************************/
2205 static WERROR
get_a_printer_driver_3(TALLOC_CTX
*mem_ctx
,
2206 struct spoolss_DriverInfo3
*driver
,
2207 const char *drivername
, const char *arch
,
2211 const char *architecture
;
2215 fstring name
, driverpath
, environment
, datafile
, configfile
, helpfile
, monitorname
, defaultdatatype
;
2217 architecture
= get_short_archi(arch
);
2218 if ( !architecture
) {
2219 return WERR_UNKNOWN_PRINTER_DRIVER
;
2222 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2224 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2227 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2229 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
2230 architecture
, version
, drivername
) < 0) {
2234 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
2237 return WERR_UNKNOWN_PRINTER_DRIVER
;
2240 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2251 driver
->driver_name
= talloc_strdup(mem_ctx
, name
);
2252 driver
->architecture
= talloc_strdup(mem_ctx
, environment
);
2253 driver
->driver_path
= talloc_strdup(mem_ctx
, driverpath
);
2254 driver
->data_file
= talloc_strdup(mem_ctx
, datafile
);
2255 driver
->config_file
= talloc_strdup(mem_ctx
, configfile
);
2256 driver
->help_file
= talloc_strdup(mem_ctx
, helpfile
);
2257 driver
->monitor_name
= talloc_strdup(mem_ctx
, monitorname
);
2258 driver
->default_datatype
= talloc_strdup(mem_ctx
, defaultdatatype
);
2262 while (len
< dbuf
.dsize
) {
2266 driver
->dependent_files
= talloc_realloc(mem_ctx
, driver
->dependent_files
, const char *, i
+2);
2267 if (!driver
->dependent_files
) {
2268 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2272 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2275 driver
->dependent_files
[i
] = talloc_strdup(mem_ctx
, file
);
2280 if (driver
->dependent_files
)
2281 driver
->dependent_files
[i
] = NULL
;
2283 SAFE_FREE(dbuf
.dptr
);
2286 if (len
!= dbuf
.dsize
) {
2287 return get_a_printer_driver_3_default(mem_ctx
, driver
, drivername
, arch
);
2293 /****************************************************************************
2294 ****************************************************************************/
2295 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, uint8
*buf
, int buflen
)
2299 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2304 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2305 nt_devmode
->devicename
,
2306 nt_devmode
->formname
,
2308 nt_devmode
->specversion
,
2309 nt_devmode
->driverversion
,
2311 nt_devmode
->driverextra
,
2312 nt_devmode
->orientation
,
2313 nt_devmode
->papersize
,
2314 nt_devmode
->paperlength
,
2315 nt_devmode
->paperwidth
,
2318 nt_devmode
->defaultsource
,
2319 nt_devmode
->printquality
,
2322 nt_devmode
->yresolution
,
2323 nt_devmode
->ttoption
,
2324 nt_devmode
->collate
,
2325 nt_devmode
->logpixels
,
2328 nt_devmode
->bitsperpel
,
2329 nt_devmode
->pelswidth
,
2330 nt_devmode
->pelsheight
,
2331 nt_devmode
->displayflags
,
2332 nt_devmode
->displayfrequency
,
2333 nt_devmode
->icmmethod
,
2334 nt_devmode
->icmintent
,
2335 nt_devmode
->mediatype
,
2336 nt_devmode
->dithertype
,
2337 nt_devmode
->reserved1
,
2338 nt_devmode
->reserved2
,
2339 nt_devmode
->panningwidth
,
2340 nt_devmode
->panningheight
,
2341 nt_devmode
->nt_dev_private
);
2343 if (nt_devmode
->nt_dev_private
) {
2344 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2345 nt_devmode
->driverextra
,
2346 nt_devmode
->nt_dev_private
);
2349 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2354 /****************************************************************************
2355 Pack all values in all printer keys
2356 ***************************************************************************/
2358 static int pack_values(NT_PRINTER_DATA
*data
, uint8
*buf
, int buflen
)
2362 struct regval_blob
*val
;
2363 struct regval_ctr
*val_ctr
;
2370 /* loop over all keys */
2372 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2373 val_ctr
= data
->keys
[i
].values
;
2374 num_values
= regval_ctr_numvals( val_ctr
);
2376 /* pack the keyname followed by a empty value */
2378 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2379 &data
->keys
[i
].name
,
2385 /* now loop over all values */
2387 for ( j
=0; j
<num_values
; j
++ ) {
2388 /* pathname should be stored as <key>\<value> */
2390 val
= regval_ctr_specific_value( val_ctr
, j
);
2391 if (asprintf(&path
, "%s\\%s",
2393 regval_name(val
)) < 0) {
2397 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2402 regval_data_p(val
) );
2404 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2412 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2418 /****************************************************************************
2419 Delete a printer - this just deletes the printer info file, any open
2420 handles are not affected.
2421 ****************************************************************************/
2423 uint32
del_a_printer(const char *sharename
)
2426 char *printdb_path
= NULL
;
2427 TALLOC_CTX
*ctx
= talloc_tos();
2429 kbuf
= make_printer_tdbkey(ctx
, sharename
);
2430 tdb_delete(tdb_printers
, kbuf
);
2432 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
2433 tdb_delete(tdb_printers
, kbuf
);
2435 close_all_print_db();
2437 if (geteuid() == sec_initial_uid()) {
2438 if (asprintf(&printdb_path
, "%s%s.tdb",
2439 cache_path("printing/"),
2443 unlink(printdb_path
);
2444 SAFE_FREE(printdb_path
);
2450 /****************************************************************************
2451 ****************************************************************************/
2452 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2458 TDB_DATA kbuf
, dbuf
;
2461 * in addprinter: no servername and the printer is the name
2462 * in setprinter: servername is \\server
2463 * and printer is \\server\\printer
2465 * Samba manages only local printers.
2466 * we currently don't support things like i
2467 * path=\\other_server\printer
2469 * We only store the printername, not \\server\printername
2472 if ( info
->servername
[0] != '\0' ) {
2473 trim_string(info
->printername
, info
->servername
, NULL
);
2474 trim_char(info
->printername
, '\\', '\0');
2475 info
->servername
[0]='\0';
2479 * JFM: one day I'll forget.
2480 * below that's info->portname because that's the SAMBA sharename
2481 * and I made NT 'thinks' it's the portname
2482 * the info->sharename is the thing you can name when you add a printer
2483 * that's the short-name when you create shared printer for 95/98
2484 * So I've made a limitation in SAMBA: you can only have 1 printer model
2485 * behind a SAMBA share.
2493 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2496 info
->default_priority
,
2513 info
->printprocessor
,
2517 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2518 retlen
= pack_values( info
->data
, buf
+len
, buflen
-len
);
2525 if (buflen
!= len
) {
2526 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
2528 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2536 kbuf
= make_printer_tdbkey(talloc_tos(), info
->sharename
);
2541 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2544 if (!W_ERROR_IS_OK(ret
))
2545 DEBUG(8, ("error updating printer to tdb on disk\n"));
2549 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2550 info
->sharename
, info
->drivername
, info
->portname
, len
));
2555 /****************************************************************************
2556 Create and allocate a default devicemode.
2557 ****************************************************************************/
2559 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
2560 const char *devicename
,
2561 struct spoolss_DeviceMode
**devmode
)
2563 struct spoolss_DeviceMode
*dm
;
2566 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
2571 dname
= talloc_asprintf(dm
, "%s", devicename
);
2572 if (dname
== NULL
) {
2575 if (strlen(dname
) > MAXDEVICENAME
) {
2576 dname
[MAXDEVICENAME
] = '\0';
2578 dm
->devicename
= dname
;
2580 dm
->formname
= talloc_strdup(dm
, "Letter");
2581 if (dm
->formname
== NULL
) {
2585 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2586 dm
->driverversion
= 0x0400;
2588 dm
->__driverextra_length
= 0;
2589 dm
->fields
= DEVMODE_FORMNAME
|
2591 DEVMODE_PRINTQUALITY
|
2592 DEVMODE_DEFAULTSOURCE
|
2596 DEVMODE_ORIENTATION
;
2597 dm
->orientation
= DMORIENT_PORTRAIT
;
2598 dm
->papersize
= DMPAPER_LETTER
;
2599 dm
->paperlength
= 0;
2603 dm
->defaultsource
= DMBIN_FORMSOURCE
;
2604 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
2605 dm
->color
= DMRES_MONOCHROME
;
2606 dm
->duplex
= DMDUP_SIMPLEX
;
2607 dm
->yresolution
= 0;
2608 dm
->ttoption
= DMTT_SUBDEV
;
2609 dm
->collate
= DMCOLLATE_FALSE
;
2619 dm
->displayflags
= 0;
2620 dm
->displayfrequency
= 0;
2623 dm
->panningwidth
= 0;
2624 dm
->panningheight
= 0;
2626 dm
->driverextra_data
.data
= NULL
;
2627 dm
->driverextra_data
.length
= 0;
2633 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
2634 struct spoolss_security_descriptor
**secdesc
)
2636 SEC_ACE ace
[5]; /* max number of ace entries */
2639 SEC_ACL
*psa
= NULL
;
2640 SEC_DESC
*psd
= NULL
;
2644 /* Create an ACE where Everyone is allowed to print */
2646 sa
= PRINTER_ACE_PRINT
;
2647 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2648 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2650 /* Add the domain admins group if we are a DC */
2653 DOM_SID domadmins_sid
;
2655 sid_compose(&domadmins_sid
, get_global_sam_sid(),
2656 DOMAIN_GROUP_RID_ADMINS
);
2658 sa
= PRINTER_ACE_FULL_CONTROL
;
2659 init_sec_ace(&ace
[i
++], &domadmins_sid
,
2660 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2661 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2662 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2663 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2665 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
2666 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
2668 sa
= PRINTER_ACE_FULL_CONTROL
;
2669 init_sec_ace(&ace
[i
++], &adm_sid
,
2670 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2671 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2672 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2673 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2676 /* add BUILTIN\Administrators as FULL CONTROL */
2678 sa
= PRINTER_ACE_FULL_CONTROL
;
2679 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2680 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2681 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2682 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2683 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2684 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2686 /* Make the security descriptor owned by the BUILTIN\Administrators */
2688 /* The ACL revision number in rpc_secdesc.h differs from the one
2689 created by NT when setting ACE entries in printer
2690 descriptors. NT4 complains about the property being edited by a
2693 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
2694 psd
= make_sec_desc(mem_ctx
,
2696 SEC_DESC_SELF_RELATIVE
,
2697 &global_sid_Builtin_Administrators
,
2698 &global_sid_Builtin_Administrators
,
2705 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2709 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2710 (unsigned int)sd_size
));
2717 /****************************************************************************
2718 Malloc and return an NT devicemode.
2719 ****************************************************************************/
2721 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2724 char adevice
[MAXDEVICENAME
];
2725 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2727 if (nt_devmode
== NULL
) {
2728 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2732 ZERO_STRUCTP(nt_devmode
);
2734 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2735 fstrcpy(nt_devmode
->devicename
, adevice
);
2737 fstrcpy(nt_devmode
->formname
, "Letter");
2739 nt_devmode
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2740 nt_devmode
->driverversion
= 0x0400;
2741 nt_devmode
->size
= 0x00DC;
2742 nt_devmode
->driverextra
= 0x0000;
2743 nt_devmode
->fields
= DEVMODE_FORMNAME
|
2745 DEVMODE_PRINTQUALITY
|
2746 DEVMODE_DEFAULTSOURCE
|
2750 DEVMODE_ORIENTATION
;
2751 nt_devmode
->orientation
= DMORIENT_PORTRAIT
;
2752 nt_devmode
->papersize
= DMPAPER_LETTER
;
2753 nt_devmode
->paperlength
= 0;
2754 nt_devmode
->paperwidth
= 0;
2755 nt_devmode
->scale
= 0x64;
2756 nt_devmode
->copies
= 1;
2757 nt_devmode
->defaultsource
= DMBIN_FORMSOURCE
;
2758 nt_devmode
->printquality
= DMRES_HIGH
; /* 0x0258 */
2759 nt_devmode
->color
= DMRES_MONOCHROME
;
2760 nt_devmode
->duplex
= DMDUP_SIMPLEX
;
2761 nt_devmode
->yresolution
= 0;
2762 nt_devmode
->ttoption
= DMTT_SUBDEV
;
2763 nt_devmode
->collate
= DMCOLLATE_FALSE
;
2764 nt_devmode
->icmmethod
= 0;
2765 nt_devmode
->icmintent
= 0;
2766 nt_devmode
->mediatype
= 0;
2767 nt_devmode
->dithertype
= 0;
2769 /* non utilisés par un driver d'imprimante */
2770 nt_devmode
->logpixels
= 0;
2771 nt_devmode
->bitsperpel
= 0;
2772 nt_devmode
->pelswidth
= 0;
2773 nt_devmode
->pelsheight
= 0;
2774 nt_devmode
->displayflags
= 0;
2775 nt_devmode
->displayfrequency
= 0;
2776 nt_devmode
->reserved1
= 0;
2777 nt_devmode
->reserved2
= 0;
2778 nt_devmode
->panningwidth
= 0;
2779 nt_devmode
->panningheight
= 0;
2781 nt_devmode
->nt_dev_private
= NULL
;
2785 /****************************************************************************
2786 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2787 ****************************************************************************/
2789 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2791 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2793 if(nt_devmode
== NULL
)
2796 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2798 SAFE_FREE(nt_devmode
->nt_dev_private
);
2799 SAFE_FREE(*devmode_ptr
);
2802 /****************************************************************************
2803 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2804 ****************************************************************************/
2806 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2808 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2813 free_nt_devicemode(&info
->devmode
);
2815 TALLOC_FREE( *info_ptr
);
2819 /****************************************************************************
2820 ****************************************************************************/
2821 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, const uint8
*buf
, int buflen
)
2825 NT_DEVICEMODE devmode
;
2827 ZERO_STRUCT(devmode
);
2829 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2831 if (!*nt_devmode
) return len
;
2833 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2837 &devmode
.specversion
,
2838 &devmode
.driverversion
,
2840 &devmode
.driverextra
,
2841 &devmode
.orientation
,
2843 &devmode
.paperlength
,
2844 &devmode
.paperwidth
,
2847 &devmode
.defaultsource
,
2848 &devmode
.printquality
,
2851 &devmode
.yresolution
,
2857 &devmode
.bitsperpel
,
2859 &devmode
.pelsheight
,
2860 &devmode
.displayflags
,
2861 &devmode
.displayfrequency
,
2865 &devmode
.dithertype
,
2868 &devmode
.panningwidth
,
2869 &devmode
.panningheight
,
2870 &devmode
.nt_dev_private
);
2872 if (devmode
.nt_dev_private
) {
2873 /* the len in tdb_unpack is an int value and
2874 * devmode.driverextra is only a short
2876 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2877 devmode
.driverextra
=(uint16
)extra_len
;
2879 /* check to catch an invalid TDB entry so we don't segfault */
2880 if (devmode
.driverextra
== 0) {
2881 devmode
.nt_dev_private
= NULL
;
2885 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2887 SAFE_FREE(devmode
.nt_dev_private
);
2891 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2892 if (devmode
.nt_dev_private
)
2893 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2898 /****************************************************************************
2899 Allocate and initialize a new slot.
2900 ***************************************************************************/
2902 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2907 if ( !name
|| !data
)
2910 /* allocate another slot in the NT_PRINTER_KEY array */
2912 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2913 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2919 key_index
= data
->num_keys
;
2921 /* initialze new key */
2923 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2925 if ( !(data
->keys
[key_index
].values
= TALLOC_ZERO_P( data
, struct regval_ctr
)) )
2930 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2935 /****************************************************************************
2936 search for a registry key name in the existing printer data
2937 ***************************************************************************/
2939 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2943 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2944 if ( strequal( data
->keys
[i
].name
, name
) ) {
2946 /* cleanup memory */
2948 TALLOC_FREE( data
->keys
[i
].name
);
2949 TALLOC_FREE( data
->keys
[i
].values
);
2951 /* if not the end of the array, move remaining elements down one slot */
2954 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2955 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2962 return data
->num_keys
;
2965 /****************************************************************************
2966 search for a registry key name in the existing printer data
2967 ***************************************************************************/
2969 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2974 if ( !data
|| !name
)
2977 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2979 /* loop over all existing keys */
2981 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2982 if ( strequal(data
->keys
[i
].name
, name
) ) {
2983 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2993 /****************************************************************************
2994 ***************************************************************************/
2996 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
3000 int num_subkeys
= 0;
3002 fstring
*subkeys_ptr
= NULL
;
3013 /* special case of asking for the top level printer data registry key names */
3015 if ( strlen(key
) == 0 ) {
3016 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3018 /* found a match, so allocate space and copy the name */
3020 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
3021 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3026 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
3033 /* asking for the subkeys of some key */
3034 /* subkey paths are stored in the key name using '\' as the delimiter */
3036 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3037 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3039 /* if we found the exact key, then break */
3040 key_len
= strlen( key
);
3041 if ( strlen(data
->keys
[i
].name
) == key_len
)
3044 /* get subkey path */
3046 p
= data
->keys
[i
].name
+ key_len
;
3049 fstrcpy( subkeyname
, p
);
3050 if ( (p
= strchr( subkeyname
, '\\' )) )
3053 /* don't add a key more than once */
3055 for ( j
=0; j
<num_subkeys
; j
++ ) {
3056 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
3060 if ( j
!= num_subkeys
)
3063 /* found a match, so allocate space and copy the name */
3065 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
3066 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3071 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
3077 /* return error if the key was not found */
3079 if ( i
== data
->num_keys
) {
3080 SAFE_FREE(subkeys_ptr
);
3085 /* tag off the end */
3088 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
3090 *subkeys
= subkeys_ptr
;
3096 static void map_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3099 regval_ctr_delvalue(ctr
, val_name
);
3100 regval_ctr_addvalue_sz(ctr
, val_name
, sz
);
3103 static void map_dword_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3106 regval_ctr_delvalue(ctr
, val_name
);
3107 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
3108 (char *) &dword
, sizeof(dword
));
3111 static void map_bool_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3114 uint8 bin_bool
= (b
? 1 : 0);
3115 regval_ctr_delvalue(ctr
, val_name
);
3116 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
3117 (char *) &bin_bool
, sizeof(bin_bool
));
3120 static void map_single_multi_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3121 const char *multi_sz
)
3128 regval_ctr_delvalue(ctr
, val_name
);
3129 regval_ctr_addvalue_multi_sz(ctr
, val_name
, a
);
3132 /****************************************************************************
3133 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3135 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3136 * @return bool indicating success or failure
3137 ***************************************************************************/
3139 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
3141 struct regval_ctr
*ctr
= NULL
;
3143 const char *dnssuffix
;
3144 char *allocated_string
= NULL
;
3145 const char *ascii_str
;
3148 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3149 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3150 ctr
= info2
->data
->keys
[i
].values
;
3152 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
3153 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
3155 /* we make the assumption that the netbios name is the same
3156 as the DNS name sinc ethe former will be what we used to
3159 dnssuffix
= get_mydnsdomname(talloc_tos());
3160 if (dnssuffix
&& *dnssuffix
) {
3161 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
3163 fstrcpy( longname
, global_myname() );
3166 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
3168 if (asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
) == -1) {
3171 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
3172 SAFE_FREE(allocated_string
);
3174 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
3175 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
3176 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
3177 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
3178 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
3179 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
3180 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
3181 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
3182 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
3184 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
3185 (info2
->attributes
&
3186 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
3188 switch (info2
->attributes
& 0x3) {
3190 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
3193 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
3196 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
3199 ascii_str
= "unknown";
3201 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
3206 /*****************************************************************
3207 ****************************************************************/
3209 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
3213 struct regval_ctr
*ctr
=NULL
;
3215 /* find the DsSpooler key */
3216 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3217 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3218 ctr
= info2
->data
->keys
[i
].values
;
3220 regval_ctr_delvalue(ctr
, "objectGUID");
3222 /* We used to store this as a REG_BINARY but that causes
3225 regval_ctr_addvalue_sz(ctr
, "objectGUID",
3226 GUID_string(talloc_tos(), &guid
));
3229 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
3230 NT_PRINTER_INFO_LEVEL
*printer
)
3234 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
, *srv_cn_escaped
, *sharename_escaped
;
3235 char *srv_dn_utf8
, **srv_cn_utf8
;
3238 const char *attrs
[] = {"objectGUID", NULL
};
3240 WERROR win_rc
= WERR_OK
;
3241 size_t converted_size
;
3243 /* build the ads mods */
3244 ctx
= talloc_init("nt_printer_publish_ads");
3249 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
3251 /* figure out where to publish */
3252 ads_find_machine_acct(ads
, &res
, global_myname());
3254 /* We use ldap_get_dn here as we need the answer
3255 * in utf8 to call ldap_explode_dn(). JRA. */
3257 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
3260 return WERR_SERVER_UNAVAILABLE
;
3262 ads_msgfree(ads
, res
);
3263 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3266 ldap_memfree(srv_dn_utf8
);
3267 return WERR_SERVER_UNAVAILABLE
;
3269 /* Now convert to CH_UNIX. */
3270 if (!pull_utf8_talloc(ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
)) {
3272 ldap_memfree(srv_dn_utf8
);
3273 ldap_memfree(srv_cn_utf8
);
3274 return WERR_SERVER_UNAVAILABLE
;
3276 if (!pull_utf8_talloc(ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
)) {
3278 ldap_memfree(srv_dn_utf8
);
3279 ldap_memfree(srv_cn_utf8
);
3280 TALLOC_FREE(srv_dn
);
3281 return WERR_SERVER_UNAVAILABLE
;
3284 ldap_memfree(srv_dn_utf8
);
3285 ldap_memfree(srv_cn_utf8
);
3287 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
3288 if (!srv_cn_escaped
) {
3290 return WERR_SERVER_UNAVAILABLE
;
3292 sharename_escaped
= escape_rdn_val_string_alloc(printer
->info_2
->sharename
);
3293 if (!sharename_escaped
) {
3294 SAFE_FREE(srv_cn_escaped
);
3296 return WERR_SERVER_UNAVAILABLE
;
3299 prt_dn
= talloc_asprintf(ctx
, "cn=%s-%s,%s", srv_cn_escaped
, sharename_escaped
, srv_dn
);
3301 SAFE_FREE(srv_cn_escaped
);
3302 SAFE_FREE(sharename_escaped
);
3304 mods
= ads_init_mods(ctx
);
3312 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3313 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3314 printer
->info_2
->sharename
);
3317 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3318 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
3320 for (i
=0; mods
[i
] != 0; i
++)
3322 mods
[i
] = (LDAPMod
*)-1;
3323 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3326 if (!ADS_ERR_OK(ads_rc
))
3327 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3329 /* retreive the guid and store it locally */
3330 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3332 ads_pull_guid(ads
, res
, &guid
);
3333 ads_msgfree(ads
, res
);
3334 store_printer_guid(printer
->info_2
, guid
);
3335 win_rc
= mod_a_printer(printer
, 2);
3342 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3343 NT_PRINTER_INFO_LEVEL
*printer
)
3346 LDAPMessage
*res
= NULL
;
3347 char *prt_dn
= NULL
;
3349 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3351 /* remove the printer from the directory */
3352 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3353 printer
->info_2
->sharename
, global_myname());
3355 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
3356 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
3358 ads_msgfree(ads
, res
);
3361 ads_rc
= ads_del_dn(ads
, prt_dn
);
3362 TALLOC_FREE(prt_dn
);
3366 ads_msgfree(ads
, res
);
3371 /****************************************************************************
3372 * Publish a printer in the directory
3374 * @param snum describing printer service
3375 * @return WERROR indicating status of publishing
3376 ***************************************************************************/
3378 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3381 ADS_STRUCT
*ads
= NULL
;
3382 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3385 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3386 if (!W_ERROR_IS_OK(win_rc
))
3390 case DSPRINT_PUBLISH
:
3391 case DSPRINT_UPDATE
:
3392 /* set the DsSpooler info and attributes */
3393 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3394 win_rc
= WERR_NOMEM
;
3398 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3400 case DSPRINT_UNPUBLISH
:
3401 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3404 win_rc
= WERR_NOT_SUPPORTED
;
3408 win_rc
= mod_a_printer(printer
, 2);
3409 if (!W_ERROR_IS_OK(win_rc
)) {
3410 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3414 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3416 DEBUG(3, ("ads_init() failed\n"));
3417 win_rc
= WERR_SERVER_UNAVAILABLE
;
3420 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3421 SAFE_FREE(ads
->auth
.password
);
3422 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3425 /* ads_connect() will find the DC for us */
3426 ads_rc
= ads_connect(ads
);
3427 if (!ADS_ERR_OK(ads_rc
)) {
3428 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3429 win_rc
= WERR_ACCESS_DENIED
;
3434 case DSPRINT_PUBLISH
:
3435 case DSPRINT_UPDATE
:
3436 win_rc
= nt_printer_publish_ads(ads
, printer
);
3438 case DSPRINT_UNPUBLISH
:
3439 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3444 free_a_printer(&printer
, 2);
3449 WERROR
check_published_printers(void)
3452 ADS_STRUCT
*ads
= NULL
;
3454 int n_services
= lp_numservices();
3455 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3457 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3459 DEBUG(3, ("ads_init() failed\n"));
3460 return WERR_SERVER_UNAVAILABLE
;
3462 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3463 SAFE_FREE(ads
->auth
.password
);
3464 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3467 /* ads_connect() will find the DC for us */
3468 ads_rc
= ads_connect(ads
);
3469 if (!ADS_ERR_OK(ads_rc
)) {
3470 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3472 ads_kdestroy("MEMORY:prtpub_cache");
3473 return WERR_ACCESS_DENIED
;
3476 for (snum
= 0; snum
< n_services
; snum
++) {
3477 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3480 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3481 lp_servicename(snum
))) &&
3482 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3483 nt_printer_publish_ads(ads
, printer
);
3485 free_a_printer(&printer
, 2);
3489 ads_kdestroy("MEMORY:prtpub_cache");
3493 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3496 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3497 struct regval_ctr
*ctr
;
3498 struct regval_blob
*guid_val
;
3504 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3506 if (!W_ERROR_IS_OK(win_rc
) ||
3507 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3508 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3509 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3510 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3512 free_a_printer(&printer
, 2);
3516 /* fetching printer guids really ought to be a separate function. */
3521 /* We used to store the guid as REG_BINARY, then swapped
3522 to REG_SZ for Vista compatibility so check for both */
3524 switch ( regval_type(guid_val
) ){
3526 blob
= data_blob_const(regval_data_p(guid_val
),
3527 regval_size(guid_val
));
3528 pull_reg_sz(talloc_tos(), NULL
, &blob
, (const char **)&guid_str
);
3529 ret
= NT_STATUS_IS_OK(GUID_from_string( guid_str
, guid
));
3530 talloc_free(guid_str
);
3533 if ( regval_size(guid_val
) != sizeof(struct GUID
) ) {
3537 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct GUID
));
3540 DEBUG(0,("is_printer_published: GUID value stored as "
3541 "invaluid type (%d)\n", regval_type(guid_val
) ));
3546 free_a_printer(&printer
, 2);
3550 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3555 WERROR
check_published_printers(void)
3560 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3565 #endif /* HAVE_ADS */
3567 /****************************************************************************
3568 ***************************************************************************/
3570 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3572 NT_PRINTER_DATA
*data
;
3574 int removed_keys
= 0;
3578 empty_slot
= data
->num_keys
;
3581 return WERR_INVALID_PARAM
;
3583 /* remove all keys */
3585 if ( !strlen(key
) ) {
3587 TALLOC_FREE( data
);
3591 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3597 /* remove a specific key (and all subkeys) */
3599 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3600 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3601 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3602 data
->keys
[i
].name
));
3604 TALLOC_FREE( data
->keys
[i
].name
);
3605 TALLOC_FREE( data
->keys
[i
].values
);
3607 /* mark the slot as empty */
3609 ZERO_STRUCTP( &data
->keys
[i
] );
3613 /* find the first empty slot */
3615 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3616 if ( !data
->keys
[i
].name
) {
3623 if ( i
== data
->num_keys
)
3624 /* nothing was removed */
3625 return WERR_INVALID_PARAM
;
3627 /* move everything down */
3629 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3630 if ( data
->keys
[i
].name
) {
3631 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3632 ZERO_STRUCTP( &data
->keys
[i
] );
3640 data
->num_keys
-= removed_keys
;
3642 /* sanity check to see if anything is left */
3644 if ( !data
->num_keys
) {
3645 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3647 SAFE_FREE( data
->keys
);
3648 ZERO_STRUCTP( data
);
3654 /****************************************************************************
3655 ***************************************************************************/
3657 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3659 WERROR result
= WERR_OK
;
3662 /* we must have names on non-zero length */
3664 if ( !key
|| !*key
|| !value
|| !*value
)
3665 return WERR_INVALID_NAME
;
3667 /* find the printer key first */
3669 key_index
= lookup_printerkey( p2
->data
, key
);
3670 if ( key_index
== -1 )
3673 /* make sure the value exists so we can return the correct error code */
3675 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3676 return WERR_BADFILE
;
3678 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3680 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3686 /****************************************************************************
3687 ***************************************************************************/
3689 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3690 uint32 type
, uint8
*data
, int real_len
)
3692 WERROR result
= WERR_OK
;
3695 /* we must have names on non-zero length */
3697 if ( !key
|| !*key
|| !value
|| !*value
)
3698 return WERR_INVALID_NAME
;
3700 /* find the printer key first */
3702 key_index
= lookup_printerkey( p2
->data
, key
);
3703 if ( key_index
== -1 )
3704 key_index
= add_new_printer_key( p2
->data
, key
);
3706 if ( key_index
== -1 )
3709 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3710 type
, (const char *)data
, real_len
);
3712 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3713 key
, value
, type
, real_len
));
3718 /****************************************************************************
3719 ***************************************************************************/
3721 struct regval_blob
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3725 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3728 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3731 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3734 /****************************************************************************
3735 Unpack a list of registry values frem the TDB
3736 ***************************************************************************/
3738 static int unpack_values(NT_PRINTER_DATA
*printer_data
, const uint8
*buf
, int buflen
)
3743 const char *valuename
= NULL
;
3744 const char *keyname
= NULL
;
3748 struct regval_blob
*regval_p
;
3751 /* add the "PrinterDriverData" key first for performance reasons */
3753 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3755 /* loop and unpack the rest of the registry values */
3759 /* check to see if there are any more registry values */
3762 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3766 /* unpack the next regval */
3768 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3774 /* lookup for subkey names which have a type of REG_NONE */
3775 /* there's no data with this entry */
3777 if ( type
== REG_NONE
) {
3778 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3779 add_new_printer_key( printer_data
, string
);
3784 * break of the keyname from the value name.
3785 * Valuenames can have embedded '\'s so be careful.
3786 * only support one level of keys. See the
3787 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3791 str
= strchr_m( string
, '\\');
3793 /* Put in "PrinterDriverData" is no key specified */
3796 keyname
= SPOOL_PRINTERDATA_KEY
;
3805 /* see if we need a new key */
3807 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3808 key_index
= add_new_printer_key( printer_data
, keyname
);
3810 if ( key_index
== -1 ) {
3811 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3816 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3818 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3819 Thanks to Martin Zielinski for the hint. */
3821 if ( type
== REG_BINARY
&&
3822 strequal( keyname
, SPOOL_DSSPOOLER_KEY
) &&
3823 strequal( valuename
, "objectGUID" ) )
3827 /* convert the GUID to a UNICODE string */
3829 memcpy( &guid
, data_p
, sizeof(struct GUID
) );
3831 regval_ctr_addvalue_sz(printer_data
->keys
[key_index
].values
,
3833 GUID_string(talloc_tos(), &guid
));
3838 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
,
3839 valuename
, type
, (const char *)data_p
,
3843 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3850 /****************************************************************************
3851 ***************************************************************************/
3853 static char *last_from
;
3854 static char *last_to
;
3856 static const char *get_last_from(void)
3864 static const char *get_last_to(void)
3872 static bool set_last_from_to(const char *from
, const char *to
)
3874 char *orig_from
= last_from
;
3875 char *orig_to
= last_to
;
3877 last_from
= SMB_STRDUP(from
);
3878 last_to
= SMB_STRDUP(to
);
3880 SAFE_FREE(orig_from
);
3883 if (!last_from
|| !last_to
) {
3884 SAFE_FREE(last_from
);
3891 static void map_to_os2_driver(fstring drivername
)
3893 char *mapfile
= lp_os2_driver_map();
3894 char **lines
= NULL
;
3898 if (!strlen(drivername
))
3904 if (strequal(drivername
,get_last_from())) {
3905 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3906 drivername
,get_last_to()));
3907 fstrcpy(drivername
,get_last_to());
3911 lines
= file_lines_load(mapfile
, &numlines
,0,NULL
);
3912 if (numlines
== 0 || lines
== NULL
) {
3913 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3918 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3920 for( i
= 0; i
< numlines
; i
++) {
3921 char *nt_name
= lines
[i
];
3922 char *os2_name
= strchr(nt_name
,'=');
3929 while (isspace(*nt_name
))
3932 if (!*nt_name
|| strchr("#;",*nt_name
))
3936 int l
= strlen(nt_name
);
3937 while (l
&& isspace(nt_name
[l
-1])) {
3943 while (isspace(*os2_name
))
3947 int l
= strlen(os2_name
);
3948 while (l
&& isspace(os2_name
[l
-1])) {
3954 if (strequal(nt_name
,drivername
)) {
3955 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3956 set_last_from_to(drivername
,os2_name
);
3957 fstrcpy(drivername
,os2_name
);
3966 /****************************************************************************
3967 Get a default printer info 2 struct.
3968 ****************************************************************************/
3970 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
,
3971 const char *servername
,
3972 const char* sharename
,
3975 int snum
= lp_servicenumber(sharename
);
3977 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3978 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
3979 servername
, sharename
);
3980 fstrcpy(info
->sharename
, sharename
);
3981 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
3983 /* by setting the driver name to an empty string, a local NT admin
3984 can now run the **local** APW to install a local printer driver
3985 for a Samba shared printer in 2.2. Without this, drivers **must** be
3986 installed on the Samba server for NT clients --jerry */
3987 #if 0 /* JERRY --do not uncomment-- */
3988 if (!*info
->drivername
)
3989 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3993 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
3995 strlcpy(info
->comment
, "", sizeof(info
->comment
));
3996 fstrcpy(info
->printprocessor
, "winprint");
3997 fstrcpy(info
->datatype
, "RAW");
4000 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
4001 /* Pull the location and comment strings from cups if we don't
4003 if ( !strlen(info
->location
) || !strlen(info
->comment
) ) {
4004 char *comment
= NULL
;
4005 char *location
= NULL
;
4006 if (cups_pull_comment_location(info
, info
->sharename
,
4007 &comment
, &location
)) {
4008 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4009 fstrcpy(info
->location
, location
);
4010 TALLOC_FREE(comment
);
4011 TALLOC_FREE(location
);
4017 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
4019 info
->starttime
= 0; /* Minutes since 12:00am GMT */
4020 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
4022 info
->default_priority
= 1;
4023 info
->setuptime
= (uint32
)time(NULL
);
4026 * I changed this as I think it is better to have a generic
4027 * DEVMODE than to crash Win2k explorer.exe --jerry
4028 * See the HP Deskjet 990c Win2k drivers for an example.
4030 * However the default devmode appears to cause problems
4031 * with the HP CLJ 8500 PCL driver. Hence the addition of
4032 * the "default devmode" parameter --jerry 22/01/2002
4035 if (lp_default_devmode(snum
)) {
4036 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
) {
4040 info
->devmode
= NULL
;
4043 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
4047 info
->data
= TALLOC_ZERO_P(info
, NT_PRINTER_DATA
);
4052 add_new_printer_key(info
->data
, SPOOL_PRINTERDATA_KEY
);
4058 free_nt_devicemode(&info
->devmode
);
4060 return WERR_ACCESS_DENIED
;
4063 /****************************************************************************
4064 ****************************************************************************/
4066 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
,
4067 const char *servername
,
4068 const char *sharename
,
4072 int snum
= lp_servicenumber(sharename
);
4073 TDB_DATA kbuf
, dbuf
;
4074 fstring printername
;
4075 char adevice
[MAXDEVICENAME
];
4076 char *comment
= NULL
;
4078 kbuf
= make_printer_tdbkey(talloc_tos(), sharename
);
4080 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
4082 return get_a_printer_2_default(info
, servername
,
4083 sharename
, get_loc_com
);
4086 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
4089 &info
->default_priority
,
4096 &info
->c_setprinter
,
4106 info
->printprocessor
,
4111 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4115 /* Samba has to have shared raw drivers. */
4116 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
4117 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
4119 /* Restore the stripped strings. */
4120 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
4122 if ( lp_force_printername(snum
) ) {
4123 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
4125 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
4128 fstrcpy(info
->printername
, printername
);
4131 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
4132 /* Pull the location and comment strings from cups if we don't
4134 if ( !strlen(info
->location
) || !strlen(info
->comment
) ) {
4135 char *location
= NULL
;
4137 if (cups_pull_comment_location(info
, info
->sharename
,
4138 &comment
, &location
)) {
4139 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4140 fstrcpy(info
->location
, location
);
4141 TALLOC_FREE(comment
);
4142 TALLOC_FREE(location
);
4148 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4151 * Some client drivers freak out if there is a NULL devmode
4152 * (probably the driver is not checking before accessing
4153 * the devmode pointer) --jerry
4155 * See comments in get_a_printer_2_default()
4158 if (lp_default_devmode(snum
) && !info
->devmode
) {
4159 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4161 info
->devmode
= construct_nt_devicemode(printername
);
4164 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
4165 if (info
->devmode
) {
4166 fstrcpy(info
->devmode
->devicename
, adevice
);
4169 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
4170 DEBUG(0,("unpack_values: talloc() failed!\n"));
4171 SAFE_FREE(dbuf
.dptr
);
4174 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4176 /* This will get the current RPC talloc context, but we should be
4177 passing this as a parameter... fixme... JRA ! */
4179 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
4180 SAFE_FREE(dbuf
.dptr
);
4184 /* Fix for OS/2 drivers. */
4186 if (get_remote_arch() == RA_OS2
) {
4187 map_to_os2_driver(info
->drivername
);
4190 SAFE_FREE(dbuf
.dptr
);
4192 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4193 sharename
, info
->printername
, info
->drivername
));
4198 /****************************************************************************
4199 Debugging function, dump at level 6 the struct in the logs.
4200 ****************************************************************************/
4201 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4204 NT_PRINTER_INFO_LEVEL_2
*info2
;
4206 DEBUG(106,("Dumping printer at level [%d]\n", level
));
4211 if (printer
->info_2
== NULL
)
4215 info2
=printer
->info_2
;
4217 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
4218 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
4219 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
4220 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
4221 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
4222 DEBUGADD(106,("status:[%d]\n", info2
->status
));
4223 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
4224 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
4225 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
4226 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
4227 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
4229 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
4230 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
4231 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
4232 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
4233 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
4234 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
4235 DEBUGADD(106,("location:[%s]\n", info2
->location
));
4236 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
4237 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
4238 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
4239 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
4245 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
4253 /****************************************************************************
4254 Update the changeid time.
4255 This is SO NASTY as some drivers need this to change, others need it
4256 static. This value will change every second, and I must hope that this
4257 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4259 ****************************************************************************/
4261 static uint32
rev_changeid(void)
4265 get_process_uptime(&tv
);
4268 /* Return changeid as msec since spooler restart */
4269 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
4272 * This setting seems to work well but is too untested
4273 * to replace the above calculation. Left in for experiementation
4274 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4276 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
4282 * The function below are the high level ones.
4283 * only those ones must be called from the spoolss code.
4287 /****************************************************************************
4288 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4289 ****************************************************************************/
4291 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4295 dump_a_printer(printer
, level
);
4301 * Update the changestamp. Emperical tests show that the
4302 * ChangeID is always updated,but c_setprinter is
4303 * global spooler variable (not per printer).
4306 /* ChangeID **must** be increasing over the lifetime
4307 of client's spoolss service in order for the
4308 client's cache to show updates */
4310 printer
->info_2
->changeid
= rev_changeid();
4313 * Because one day someone will ask:
4314 * NT->NT An admin connection to a remote
4315 * printer show changes imeediately in
4316 * the properities dialog
4318 * A non-admin connection will only show the
4319 * changes after viewing the properites page
4320 * 2 times. Seems to be related to a
4321 * race condition in the client between the spooler
4322 * updating the local cache and the Explorer.exe GUI
4323 * actually displaying the properties.
4325 * This is fixed in Win2k. admin/non-admin
4326 * connections both display changes immediately.
4331 result
=update_a_printer_2(printer
->info_2
);
4335 result
=WERR_UNKNOWN_LEVEL
;
4342 /****************************************************************************
4343 Initialize printer devmode & data with previously saved driver init values.
4344 ****************************************************************************/
4346 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
4351 NT_PRINTER_INFO_LEVEL_2 info
;
4357 * Delete any printer data 'values' already set. When called for driver
4358 * replace, there will generally be some, but during an add printer, there
4359 * should not be any (if there are delete them).
4362 if ( info_ptr
->data
)
4363 delete_all_printer_data( info_ptr
, "" );
4365 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
,
4366 info_ptr
->drivername
) < 0) {
4370 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
4373 * When changing to a driver that has no init info in the tdb, remove
4374 * the previous drivers init info and leave the new on blank.
4376 free_nt_devicemode(&info_ptr
->devmode
);
4383 * Get the saved DEVMODE..
4386 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4389 * The saved DEVMODE contains the devicename from the printer used during
4390 * the initialization save. Change it to reflect the new printer.
4393 if ( info
.devmode
) {
4394 ZERO_STRUCT(info
.devmode
->devicename
);
4395 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
4399 * NT/2k does not change out the entire DeviceMode of a printer
4400 * when changing the driver. Only the driverextra, private, &
4401 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4403 * Later examination revealed that Windows NT/2k does reset the
4404 * the printer's device mode, bit **only** when you change a
4405 * property of the device mode such as the page orientation.
4410 /* Bind the saved DEVMODE to the new the printer */
4412 free_nt_devicemode(&info_ptr
->devmode
);
4413 info_ptr
->devmode
= info
.devmode
;
4415 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4416 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
4418 /* Add the printer data 'values' to the new printer */
4420 if ( !(info_ptr
->data
= TALLOC_ZERO_P( info_ptr
, NT_PRINTER_DATA
)) ) {
4421 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4425 len
+= unpack_values( info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4427 SAFE_FREE(dbuf
.dptr
);
4432 /****************************************************************************
4433 Initialize printer devmode & data with previously saved driver init values.
4434 When a printer is created using AddPrinter, the drivername bound to the
4435 printer is used to lookup previously saved driver initialization info, which
4436 is bound to the new printer.
4437 ****************************************************************************/
4439 bool set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4441 bool result
= False
;
4445 result
= set_driver_init_2(printer
->info_2
);
4449 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4457 /****************************************************************************
4458 Delete driver init data stored for a specified driver
4459 ****************************************************************************/
4461 bool del_driver_init(const char *drivername
)
4466 if (!drivername
|| !*drivername
) {
4467 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4471 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
, drivername
) < 0) {
4475 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4478 ret
= (tdb_delete_bystring(tdb_drivers
, key
) == 0);
4483 /****************************************************************************
4484 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4485 in the tdb. Note: this is different from the driver entry and the printer
4486 entry. There should be a single driver init entry for each driver regardless
4487 of whether it was installed from NT or 2K. Technically, they should be
4488 different, but they work out to the same struct.
4489 ****************************************************************************/
4491 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4495 int buflen
, len
, ret
;
4504 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4506 retlen
= pack_values( info
->data
, buf
+len
, buflen
-len
);
4514 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
4516 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4525 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
) < 0) {
4533 ret
= tdb_store_bystring(tdb_drivers
, key
, dbuf
, TDB_REPLACE
);
4537 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4541 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4542 info
->sharename
, info
->drivername
));
4547 /****************************************************************************
4548 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4549 ****************************************************************************/
4551 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4555 dump_a_printer(printer
, level
);
4559 result
= update_driver_init_2(printer
->info_2
);
4569 /****************************************************************************
4570 Convert the printer data value, a REG_BINARY array, into an initialization
4571 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4572 got to keep the endians happy :).
4573 ****************************************************************************/
4575 static bool convert_driver_init(TALLOC_CTX
*mem_ctx
, NT_DEVICEMODE
*nt_devmode
,
4576 const uint8_t *data
, uint32_t data_len
)
4578 struct spoolss_DeviceMode devmode
;
4579 enum ndr_err_code ndr_err
;
4582 ZERO_STRUCT(devmode
);
4584 blob
= data_blob_const(data
, data_len
);
4586 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, NULL
, &devmode
,
4587 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_DeviceMode
);
4588 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4589 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4593 return convert_devicemode("", &devmode
, &nt_devmode
);
4596 /****************************************************************************
4597 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4599 1. Use the driver's config DLL to this UNC printername and:
4600 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4601 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4602 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4604 The last step triggers saving the "driver initialization" information for
4605 this printer into the tdb. Later, new printers that use this driver will
4606 have this initialization information bound to them. This simulates the
4607 driver initialization, as if it had run on the Samba server (as it would
4610 The Win32 client side code requirement sucks! But until we can run arbitrary
4611 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4613 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4614 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4615 about it and you will realize why. JRR 010720
4616 ****************************************************************************/
4618 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4620 WERROR status
= WERR_OK
;
4621 TALLOC_CTX
*ctx
= NULL
;
4622 NT_DEVICEMODE
*nt_devmode
= NULL
;
4623 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4626 * When the DEVMODE is already set on the printer, don't try to unpack it.
4628 DEBUG(8,("save_driver_init_2: Enter...\n"));
4630 if ( !printer
->info_2
->devmode
&& data_len
) {
4632 * Set devmode on printer info, so entire printer initialization can be
4636 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4639 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4640 status
= WERR_NOMEM
;
4644 ZERO_STRUCTP(nt_devmode
);
4647 * The DEVMODE is held in the 'data' component of the param in raw binary.
4648 * Convert it to to a devmode structure
4650 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4651 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4652 status
= WERR_INVALID_PARAM
;
4656 printer
->info_2
->devmode
= nt_devmode
;
4660 * Pack up and add (or update) the DEVMODE and any current printer data to
4661 * a 'driver init' element in the tdb
4665 if ( update_driver_init(printer
, 2) != 0 ) {
4666 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4667 status
= WERR_NOMEM
;
4672 * If driver initialization info was successfully saved, set the current
4673 * printer to match it. This allows initialization of the current printer
4674 * as well as the driver.
4676 status
= mod_a_printer(printer
, 2);
4677 if (!W_ERROR_IS_OK(status
)) {
4678 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4679 printer
->info_2
->printername
));
4683 talloc_destroy(ctx
);
4684 free_nt_devicemode( &nt_devmode
);
4686 printer
->info_2
->devmode
= tmp_devmode
;
4691 /****************************************************************************
4692 Update the driver init info (DEVMODE and specifics) for a printer
4693 ****************************************************************************/
4695 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4697 WERROR status
= WERR_OK
;
4701 status
= save_driver_init_2( printer
, data
, data_len
);
4704 status
= WERR_UNKNOWN_LEVEL
;
4711 /****************************************************************************
4712 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4714 Previously the code had a memory allocation problem because it always
4715 used the TALLOC_CTX from the Printer_entry*. This context lasts
4716 as a long as the original handle is open. So if the client made a lot
4717 of getprinter[data]() calls, the memory usage would climb. Now we use
4718 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4719 still use the Printer_entry->ctx for maintaining the cache copy though
4720 since that object must live as long as the handle by definition.
4723 ****************************************************************************/
4725 static WERROR
get_a_printer_internal( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4726 const char *sharename
, bool get_loc_com
)
4731 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4733 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4734 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4740 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4741 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4742 TALLOC_FREE( *pp_printer
);
4747 fstrcpy( servername
, print_hnd
->servername
);
4749 fstrcpy( servername
, "%L" );
4750 standard_sub_basic( "", "", servername
,
4751 sizeof(servername
)-1 );
4754 result
= get_a_printer_2( (*pp_printer
)->info_2
,
4755 servername
, sharename
, get_loc_com
);
4757 /* we have a new printer now. Save it with this handle */
4759 if ( !W_ERROR_IS_OK(result
) ) {
4760 TALLOC_FREE( *pp_printer
);
4761 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4762 sharename
, (unsigned int)level
, win_errstr(result
)));
4766 dump_a_printer( *pp_printer
, level
);
4771 TALLOC_FREE( *pp_printer
);
4772 return WERR_UNKNOWN_LEVEL
;
4778 WERROR
get_a_printer( Printer_entry
*print_hnd
,
4779 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4781 const char *sharename
)
4783 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4787 WERROR
get_a_printer_search( Printer_entry
*print_hnd
,
4788 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4790 const char *sharename
)
4792 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4796 /****************************************************************************
4797 Deletes a NT_PRINTER_INFO_LEVEL struct.
4798 ****************************************************************************/
4800 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4802 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4809 if ( printer
->info_2
)
4810 free_nt_printer_info_level_2(&printer
->info_2
);
4814 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4818 TALLOC_FREE(*pp_printer
);
4823 /****************************************************************************
4824 ****************************************************************************/
4826 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
4827 struct spoolss_DriverInfo8
*_info8
)
4829 struct spoolss_DriverInfo8 info8
;
4835 info8
.version
= r
->info
.info3
->version
;
4836 info8
.driver_name
= r
->info
.info3
->driver_name
;
4837 info8
.architecture
= r
->info
.info3
->architecture
;
4838 info8
.driver_path
= r
->info
.info3
->driver_path
;
4839 info8
.data_file
= r
->info
.info3
->data_file
;
4840 info8
.config_file
= r
->info
.info3
->config_file
;
4841 info8
.help_file
= r
->info
.info3
->help_file
;
4842 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
4843 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
4844 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
4845 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
4849 info8
.version
= r
->info
.info6
->version
;
4850 info8
.driver_name
= r
->info
.info6
->driver_name
;
4851 info8
.architecture
= r
->info
.info6
->architecture
;
4852 info8
.driver_path
= r
->info
.info6
->driver_path
;
4853 info8
.data_file
= r
->info
.info6
->data_file
;
4854 info8
.config_file
= r
->info
.info6
->config_file
;
4855 info8
.help_file
= r
->info
.info6
->help_file
;
4856 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
4857 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
4858 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
4859 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
4861 info8
.driver_date
= r
->info
.info6
->driver_date
;
4862 info8
.driver_version
= r
->info
.info6
->driver_version
;
4863 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
4864 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
4865 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
4866 info8
.provider
= r
->info
.info6
->provider
;
4869 info8
.version
= r
->info
.info8
->version
;
4870 info8
.driver_name
= r
->info
.info8
->driver_name
;
4871 info8
.architecture
= r
->info
.info8
->architecture
;
4872 info8
.driver_path
= r
->info
.info8
->driver_path
;
4873 info8
.data_file
= r
->info
.info8
->data_file
;
4874 info8
.config_file
= r
->info
.info8
->config_file
;
4875 info8
.help_file
= r
->info
.info8
->help_file
;
4876 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
4877 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
4878 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
4879 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
4881 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
4882 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
4884 info8
.driver_date
= r
->info
.info8
->driver_date
;
4885 info8
.driver_version
= r
->info
.info8
->driver_version
;
4886 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
4887 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
4888 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
4889 info8
.provider
= r
->info
.info8
->provider
;
4890 info8
.print_processor
= r
->info
.info8
->print_processor
;
4891 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
4892 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
4893 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
4895 info8
.inf_path
= r
->info
.info8
->inf_path
;
4896 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
4897 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
4898 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
4900 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
4901 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
4913 uint32_t add_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4914 struct spoolss_AddDriverInfoCtr
*r
,
4918 struct spoolss_DriverInfo8 info8
;
4922 DEBUG(10,("adding a printer at level [%d]\n", r
->level
));
4924 if (!driver_info_ctr_to_info8(r
, &info8
)) {
4928 *driver_name
= talloc_strdup(mem_ctx
, info8
.driver_name
);
4929 if (!*driver_name
) {
4932 *version
= info8
.version
;
4934 return add_a_printer_driver_8(&info8
);
4937 /****************************************************************************
4938 ****************************************************************************/
4940 WERROR
get_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4941 struct spoolss_DriverInfo8
**driver
,
4942 const char *drivername
, const char *architecture
,
4946 struct spoolss_DriverInfo3 info3
;
4947 struct spoolss_DriverInfo8
*info8
;
4951 /* Sometime we just want any version of the driver */
4953 if (version
== DRIVER_ANY_VERSION
) {
4954 /* look for Win2k first and then for NT4 */
4955 result
= get_a_printer_driver_3(mem_ctx
,
4959 if (!W_ERROR_IS_OK(result
)) {
4960 result
= get_a_printer_driver_3(mem_ctx
,
4966 result
= get_a_printer_driver_3(mem_ctx
,
4973 if (!W_ERROR_IS_OK(result
)) {
4977 info8
= talloc_zero(mem_ctx
, struct spoolss_DriverInfo8
);
4982 info8
->version
= info3
.version
;
4983 info8
->driver_name
= info3
.driver_name
;
4984 info8
->architecture
= info3
.architecture
;
4985 info8
->driver_path
= info3
.driver_path
;
4986 info8
->data_file
= info3
.data_file
;
4987 info8
->config_file
= info3
.config_file
;
4988 info8
->help_file
= info3
.help_file
;
4989 info8
->dependent_files
= info3
.dependent_files
;
4990 info8
->monitor_name
= info3
.monitor_name
;
4991 info8
->default_datatype
= info3
.default_datatype
;
4998 /****************************************************************************
4999 ****************************************************************************/
5001 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8
*driver
)
5003 talloc_free(driver
);
5008 /****************************************************************************
5009 Determine whether or not a particular driver is currently assigned
5011 ****************************************************************************/
5013 bool printer_driver_in_use(const struct spoolss_DriverInfo8
*r
)
5016 int n_services
= lp_numservices();
5017 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5018 bool in_use
= False
;
5024 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
5026 /* loop through the printers.tdb and check for the drivername */
5028 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
5029 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
5032 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
5035 if (strequal(r
->driver_name
, printer
->info_2
->drivername
))
5038 free_a_printer( &printer
, 2 );
5041 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
5044 struct spoolss_DriverInfo8
*d
;
5047 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
5049 /* we can still remove the driver if there is one of
5050 "Windows NT x86" version 2 or 3 left */
5052 if (!strequal("Windows NT x86", r
->architecture
)) {
5053 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", DRIVER_ANY_VERSION
);
5056 switch (r
->version
) {
5058 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 3);
5061 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 2);
5064 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
5066 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
5071 /* now check the error code */
5073 if ( W_ERROR_IS_OK(werr
) ) {
5074 /* it's ok to remove the driver, we have other architctures left */
5076 free_a_printer_driver(d
);
5080 /* report that the driver is not in use by default */
5086 /**********************************************************************
5087 Check to see if a ogiven file is in use by *info
5088 *********************************************************************/
5090 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
5097 /* mz: skip files that are in the list but already deleted */
5098 if (!file
|| !file
[0]) {
5102 if (strequal(file
, info
->driver_path
))
5105 if (strequal(file
, info
->data_file
))
5108 if (strequal(file
, info
->config_file
))
5111 if (strequal(file
, info
->help_file
))
5114 /* see of there are any dependent files to examine */
5116 if (!info
->dependent_files
)
5119 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
5120 if (strequal(file
, info
->dependent_files
[i
]))
5129 /**********************************************************************
5130 Utility function to remove the dependent file pointed to by the
5131 input parameter from the list
5132 *********************************************************************/
5134 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
5137 /* bump everything down a slot */
5139 while (files
&& files
[idx
+1]) {
5140 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
5149 /**********************************************************************
5150 Check if any of the files used by src are also used by drv
5151 *********************************************************************/
5153 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
5154 struct spoolss_DriverInfo8
*src
,
5155 const struct spoolss_DriverInfo8
*drv
)
5157 bool in_use
= False
;
5163 /* check each file. Remove it from the src structure if it overlaps */
5165 if (drv_file_in_use(src
->driver_path
, drv
)) {
5167 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
5168 src
->driver_path
= talloc_strdup(mem_ctx
, "");
5169 if (!src
->driver_path
) { return false; }
5172 if (drv_file_in_use(src
->data_file
, drv
)) {
5174 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
5175 src
->data_file
= talloc_strdup(mem_ctx
, "");
5176 if (!src
->data_file
) { return false; }
5179 if (drv_file_in_use(src
->config_file
, drv
)) {
5181 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
5182 src
->config_file
= talloc_strdup(mem_ctx
, "");
5183 if (!src
->config_file
) { return false; }
5186 if (drv_file_in_use(src
->help_file
, drv
)) {
5188 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
5189 src
->help_file
= talloc_strdup(mem_ctx
, "");
5190 if (!src
->help_file
) { return false; }
5193 /* are there any dependentfiles to examine? */
5195 if (!src
->dependent_files
)
5198 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
5199 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
5201 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
5202 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
5210 /****************************************************************************
5211 Determine whether or not a particular driver files are currently being
5212 used by any other driver.
5214 Return value is True if any files were in use by other drivers
5215 and False otherwise.
5217 Upon return, *info has been modified to only contain the driver files
5218 which are not in use
5222 This needs to check all drivers to ensure that all files in use
5223 have been removed from *info, not just the ones in the first
5225 ****************************************************************************/
5227 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
5228 struct spoolss_DriverInfo8
*info
)
5233 fstring
*list
= NULL
;
5234 struct spoolss_DriverInfo8
*driver
;
5235 bool in_use
= false;
5240 version
= info
->version
;
5242 /* loop over all driver versions */
5244 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5246 /* get the list of drivers */
5249 ndrivers
= get_ntdrivers(&list
, info
->architecture
, version
);
5251 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5252 ndrivers
, info
->architecture
, version
));
5254 /* check each driver for overlap in files */
5256 for (i
=0; i
<ndrivers
; i
++) {
5257 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5261 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, list
[i
], info
->architecture
, version
))) {
5266 /* check if d2 uses any files from d1 */
5267 /* only if this is a different driver than the one being deleted */
5269 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
5270 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
5271 /* mz: Do not instantly return -
5272 * we need to ensure this file isn't
5273 * also in use by other drivers. */
5278 free_a_printer_driver(driver
);
5283 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5288 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
5291 struct smb_filename
*smb_fname
= NULL
;
5294 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
5296 if (!NT_STATUS_IS_OK(status
)) {
5300 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
5302 TALLOC_FREE(smb_fname
);
5306 /****************************************************************************
5307 Actually delete the driver files. Make sure that
5308 printer_driver_files_in_use() return False before calling
5310 ****************************************************************************/
5312 static bool delete_driver_files(struct pipes_struct
*rpc_pipe
,
5313 const struct spoolss_DriverInfo8
*r
)
5318 connection_struct
*conn
;
5321 fstring printdollar
;
5322 int printdollar_snum
;
5329 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5330 r
->driver_name
, r
->version
));
5332 fstrcpy(printdollar
, "print$");
5334 printdollar_snum
= find_service(printdollar
);
5335 if (printdollar_snum
== -1) {
5339 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
5340 lp_pathname(printdollar_snum
),
5341 rpc_pipe
->server_info
, &oldcwd
);
5342 if (!NT_STATUS_IS_OK(nt_status
)) {
5343 DEBUG(0,("delete_driver_files: create_conn_struct "
5344 "returned %s\n", nt_errstr(nt_status
)));
5348 if ( !CAN_WRITE(conn
) ) {
5349 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5353 /* now delete the files; must strip the '\print$' string from
5356 if (r
->driver_path
&& r
->driver_path
[0]) {
5357 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
5359 DEBUG(10,("deleting driverfile [%s]\n", s
));
5360 driver_unlink_internals(conn
, file
);
5364 if (r
->config_file
&& r
->config_file
[0]) {
5365 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
5367 DEBUG(10,("deleting configfile [%s]\n", s
));
5368 driver_unlink_internals(conn
, file
);
5372 if (r
->data_file
&& r
->data_file
[0]) {
5373 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
5375 DEBUG(10,("deleting datafile [%s]\n", s
));
5376 driver_unlink_internals(conn
, file
);
5380 if (r
->help_file
&& r
->help_file
[0]) {
5381 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
5383 DEBUG(10,("deleting helpfile [%s]\n", s
));
5384 driver_unlink_internals(conn
, file
);
5388 /* check if we are done removing files */
5390 if (r
->dependent_files
) {
5391 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
5394 /* bypass the "\print$" portion of the path */
5396 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
5398 DEBUG(10,("deleting dependent file [%s]\n", file
));
5399 driver_unlink_internals(conn
, file
);
5411 vfs_ChDir(conn
, oldcwd
);
5417 /****************************************************************************
5418 Remove a printer driver from the TDB. This assumes that the the driver was
5419 previously looked up.
5420 ***************************************************************************/
5422 WERROR
delete_printer_driver(struct pipes_struct
*rpc_pipe
,
5423 const struct spoolss_DriverInfo8
*r
,
5424 uint32 version
, bool delete_files
)
5430 /* delete the tdb data first */
5432 arch
= get_short_archi(r
->architecture
);
5434 return WERR_UNKNOWN_PRINTER_DRIVER
;
5436 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
5437 arch
, version
, r
->driver_name
) < 0) {
5441 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5442 key
, delete_files
? "TRUE" : "FALSE" ));
5444 /* check if the driver actually exists for this environment */
5446 dbuf
= tdb_fetch_bystring( tdb_drivers
, key
);
5448 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
5450 return WERR_UNKNOWN_PRINTER_DRIVER
;
5453 SAFE_FREE( dbuf
.dptr
);
5455 /* ok... the driver exists so the delete should return success */
5457 if (tdb_delete_bystring(tdb_drivers
, key
) == -1) {
5458 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
5460 return WERR_ACCESS_DENIED
;
5464 * now delete any associated files if delete_files == True
5465 * even if this part failes, we return succes because the
5466 * driver doesn not exist any more
5470 delete_driver_files(rpc_pipe
, r
);
5472 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
5478 /****************************************************************************
5479 Store a security desc for a printer.
5480 ****************************************************************************/
5482 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
5484 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5485 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
5486 TALLOC_CTX
*mem_ctx
= NULL
;
5493 mem_ctx
= talloc_init("nt_printing_setsec");
5494 if (mem_ctx
== NULL
)
5497 /* The old owner and group sids of the security descriptor are not
5498 present when new ACEs are added or removed by changing printer
5499 permissions through NT. If they are NULL in the new security
5500 descriptor then copy them over from the old one. */
5502 if (!secdesc_ctr
->sd
->owner_sid
|| !secdesc_ctr
->sd
->group_sid
) {
5503 DOM_SID
*owner_sid
, *group_sid
;
5504 SEC_ACL
*dacl
, *sacl
;
5505 SEC_DESC
*psd
= NULL
;
5508 if (!nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
)) {
5509 status
= WERR_NOMEM
;
5513 /* Pick out correct owner and group sids */
5515 owner_sid
= secdesc_ctr
->sd
->owner_sid
?
5516 secdesc_ctr
->sd
->owner_sid
:
5517 old_secdesc_ctr
->sd
->owner_sid
;
5519 group_sid
= secdesc_ctr
->sd
->group_sid
?
5520 secdesc_ctr
->sd
->group_sid
:
5521 old_secdesc_ctr
->sd
->group_sid
;
5523 dacl
= secdesc_ctr
->sd
->dacl
?
5524 secdesc_ctr
->sd
->dacl
:
5525 old_secdesc_ctr
->sd
->dacl
;
5527 sacl
= secdesc_ctr
->sd
->sacl
?
5528 secdesc_ctr
->sd
->sacl
:
5529 old_secdesc_ctr
->sd
->sacl
;
5531 /* Make a deep copy of the security descriptor */
5533 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sd
->revision
, secdesc_ctr
->sd
->type
,
5534 owner_sid
, group_sid
,
5540 status
= WERR_NOMEM
;
5544 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
5547 if (!new_secdesc_ctr
) {
5548 new_secdesc_ctr
= secdesc_ctr
;
5551 /* Store the security descriptor in a tdb */
5553 nt_status
= marshall_sec_desc_buf(mem_ctx
, new_secdesc_ctr
,
5554 &blob
.data
, &blob
.length
);
5555 if (!NT_STATUS_IS_OK(nt_status
)) {
5556 status
= ntstatus_to_werror(nt_status
);
5560 kbuf
= make_printers_secdesc_tdbkey(mem_ctx
, sharename
);
5562 dbuf
.dptr
= (unsigned char *)blob
.data
;
5563 dbuf
.dsize
= blob
.length
;
5565 if (tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
)==0) {
5568 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
5569 status
= WERR_BADFUNC
;
5572 /* Free malloc'ed memory */
5573 talloc_free(blob
.data
);
5578 talloc_destroy(mem_ctx
);
5582 /****************************************************************************
5583 Construct a default security descriptor buffer for a printer.
5584 ****************************************************************************/
5586 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5588 SEC_ACE ace
[5]; /* max number of ace entries */
5591 SEC_ACL
*psa
= NULL
;
5592 SEC_DESC_BUF
*sdb
= NULL
;
5593 SEC_DESC
*psd
= NULL
;
5597 /* Create an ACE where Everyone is allowed to print */
5599 sa
= PRINTER_ACE_PRINT
;
5600 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5601 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5603 /* Add the domain admins group if we are a DC */
5606 DOM_SID domadmins_sid
;
5608 sid_compose(&domadmins_sid
, get_global_sam_sid(),
5609 DOMAIN_GROUP_RID_ADMINS
);
5611 sa
= PRINTER_ACE_FULL_CONTROL
;
5612 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5613 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5614 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5615 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5616 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5618 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5619 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5621 sa
= PRINTER_ACE_FULL_CONTROL
;
5622 init_sec_ace(&ace
[i
++], &adm_sid
,
5623 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5624 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5625 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5626 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5629 /* add BUILTIN\Administrators as FULL CONTROL */
5631 sa
= PRINTER_ACE_FULL_CONTROL
;
5632 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5633 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5634 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5635 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5636 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5637 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5639 /* Make the security descriptor owned by the BUILTIN\Administrators */
5641 /* The ACL revision number in rpc_secdesc.h differs from the one
5642 created by NT when setting ACE entries in printer
5643 descriptors. NT4 complains about the property being edited by a
5646 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5647 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5648 &global_sid_Builtin_Administrators
,
5649 &global_sid_Builtin_Administrators
,
5650 NULL
, psa
, &sd_size
);
5654 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5658 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5660 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5661 (unsigned int)sd_size
));
5666 /****************************************************************************
5667 Get a security desc for a printer.
5668 ****************************************************************************/
5670 bool nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5678 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5679 sharename
= temp
+ 1;
5682 /* Fetch security descriptor from tdb */
5684 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
5686 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
5689 status
= unmarshall_sec_desc_buf(ctx
, dbuf
.dptr
, dbuf
.dsize
,
5691 SAFE_FREE(dbuf
.dptr
);
5693 if (NT_STATUS_IS_OK(status
)) {
5698 *secdesc_ctr
= construct_default_printer_sdb(ctx
);
5699 if (!*secdesc_ctr
) {
5703 status
= marshall_sec_desc_buf(ctx
, *secdesc_ctr
,
5704 &blob
.data
, &blob
.length
);
5705 if (NT_STATUS_IS_OK(status
)) {
5706 dbuf
.dptr
= (unsigned char *)blob
.data
;
5707 dbuf
.dsize
= blob
.length
;
5708 tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
);
5709 talloc_free(blob
.data
);
5712 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5713 this security descriptor has been created when winbindd was
5714 down. Take ownership of security descriptor. */
5716 if (sid_equal((*secdesc_ctr
)->sd
->owner_sid
, &global_sid_World
)) {
5719 /* Change sd owner to workgroup administrator */
5721 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5722 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5723 SEC_DESC
*psd
= NULL
;
5728 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5730 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sd
->revision
, (*secdesc_ctr
)->sd
->type
,
5732 (*secdesc_ctr
)->sd
->group_sid
,
5733 (*secdesc_ctr
)->sd
->sacl
,
5734 (*secdesc_ctr
)->sd
->dacl
,
5741 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5742 if (!new_secdesc_ctr
) {
5746 /* Swap with other one */
5748 *secdesc_ctr
= new_secdesc_ctr
;
5752 nt_printing_setsec(sharename
, *secdesc_ctr
);
5756 if (DEBUGLEVEL
>= 10) {
5757 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sd
->dacl
;
5760 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5761 sharename
, the_acl
->num_aces
));
5763 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5764 DEBUG(10, ("%s %d %d 0x%08x\n",
5765 sid_string_dbg(&the_acl
->aces
[i
].trustee
),
5766 the_acl
->aces
[i
].type
, the_acl
->aces
[i
].flags
,
5767 the_acl
->aces
[i
].access_mask
));
5776 1: level not implemented
5777 2: file doesn't exist
5778 3: can't allocate memory
5779 4: can't free memory
5780 5: non existant struct
5784 A printer and a printer driver are 2 different things.
5785 NT manages them separatelly, Samba does the same.
5786 Why ? Simply because it's easier and it makes sense !
5788 Now explanation: You have 3 printers behind your samba server,
5789 2 of them are the same make and model (laser A and B). But laser B
5790 has an 3000 sheet feeder and laser A doesn't such an option.
5791 Your third printer is an old dot-matrix model for the accounting :-).
5793 If the /usr/local/samba/lib directory (default dir), you will have
5794 5 files to describe all of this.
5796 3 files for the printers (1 by printer):
5799 NTprinter_accounting
5800 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5801 NTdriver_printer model X
5802 NTdriver_printer model Y
5804 jfm: I should use this comment for the text file to explain
5805 same thing for the forms BTW.
5806 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5810 /* Convert generic access rights to printer object specific access rights.
5811 It turns out that NT4 security descriptors use generic access rights and
5812 NT5 the object specific ones. */
5814 void map_printer_permissions(SEC_DESC
*sd
)
5818 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5819 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5820 &printer_generic_mapping
);
5824 void map_job_permissions(SEC_DESC
*sd
)
5828 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5829 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5830 &job_generic_mapping
);
5835 /****************************************************************************
5836 Check a user has permissions to perform the given operation. We use the
5837 permission constants defined in include/rpc_spoolss.h to check the various
5838 actions we perform when checking printer access.
5840 PRINTER_ACCESS_ADMINISTER:
5841 print_queue_pause, print_queue_resume, update_printer_sec,
5842 update_printer, spoolss_addprinterex_level_2,
5843 _spoolss_setprinterdata
5848 JOB_ACCESS_ADMINISTER:
5849 print_job_delete, print_job_pause, print_job_resume,
5852 Try access control in the following order (for performance reasons):
5853 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5854 2) check security descriptor (bit comparisons in memory)
5855 3) "printer admins" (may result in numerous calls to winbind)
5857 ****************************************************************************/
5858 bool print_access_check(struct auth_serversupplied_info
*server_info
, int snum
,
5861 SEC_DESC_BUF
*secdesc
= NULL
;
5862 uint32 access_granted
;
5865 TALLOC_CTX
*mem_ctx
= NULL
;
5866 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5868 /* If user is NULL then use the current_user structure */
5870 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5872 if (server_info
->utok
.uid
== sec_initial_uid()
5873 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
5877 /* Get printer name */
5879 pname
= PRINTERNAME(snum
);
5881 if (!pname
|| !*pname
) {
5886 /* Get printer security descriptor */
5888 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5893 if (!nt_printing_getsec(mem_ctx
, pname
, &secdesc
)) {
5894 talloc_destroy(mem_ctx
);
5899 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5900 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5902 /* Create a child security descriptor to check permissions
5903 against. This is because print jobs are child objects
5904 objects of a printer. */
5906 status
= se_create_child_secdesc_buf(mem_ctx
, &secdesc
, parent_secdesc
->sd
, False
);
5908 if (!NT_STATUS_IS_OK(status
)) {
5909 talloc_destroy(mem_ctx
);
5910 errno
= map_errno_from_nt_status(status
);
5914 map_job_permissions(secdesc
->sd
);
5916 map_printer_permissions(secdesc
->sd
);
5920 status
= se_access_check(secdesc
->sd
, server_info
->ptok
, access_type
,
5923 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
5925 /* see if we need to try the printer admin list */
5927 if (!NT_STATUS_IS_OK(status
) &&
5928 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
5929 NULL
, NULL
, server_info
->ptok
,
5930 lp_printer_admin(snum
)))) {
5931 talloc_destroy(mem_ctx
);
5935 talloc_destroy(mem_ctx
);
5937 if (!NT_STATUS_IS_OK(status
)) {
5941 return NT_STATUS_IS_OK(status
);
5944 /****************************************************************************
5945 Check the time parameters allow a print operation.
5946 *****************************************************************************/
5948 bool print_time_access_check(const char *servicename
)
5950 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5952 time_t now
= time(NULL
);
5956 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
5959 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5963 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5965 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5968 free_a_printer(&printer
, 2);
5976 /****************************************************************************
5977 Fill in the servername sent in the _spoolss_open_printer_ex() call
5978 ****************************************************************************/
5980 char* get_server_name( Printer_entry
*printer
)
5982 return printer
->servername
;