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/>.
24 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
25 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
26 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
28 #define FORMS_PREFIX "FORMS/"
29 #define DRIVERS_PREFIX "DRIVERS/"
30 #define DRIVERS_PREFIX8 "DRIVERS8/"
31 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
32 #define PRINTERS_PREFIX "PRINTERS/"
33 #define SECDESC_PREFIX "SECDESC/"
34 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
36 #define NTDRIVERS_DATABASE_VERSION_1 1
37 #define NTDRIVERS_DATABASE_VERSION_2 2
38 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
39 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
40 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
42 /* Map generic permissions to printer object specific permissions */
44 const struct generic_mapping printer_generic_mapping
= {
51 const struct standard_mapping printer_std_mapping
= {
58 /* Map generic permissions to print server object specific permissions */
60 const struct generic_mapping printserver_generic_mapping
= {
67 const struct generic_mapping printserver_std_mapping
= {
74 /* Map generic permissions to job object specific permissions */
76 const struct generic_mapping job_generic_mapping
= {
83 /* We need one default form to support our default printer. Msoft adds the
84 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
85 array index). Letter is always first, so (for the current code) additions
86 always put things in the correct order. */
87 static const nt_forms_struct default_forms
[] = {
88 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
89 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
91 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
92 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
93 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
94 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
95 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
96 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
97 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
99 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
100 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
101 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
102 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
103 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
104 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
105 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
106 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
107 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
108 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
109 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
110 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
111 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
112 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
113 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
114 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
115 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
116 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
117 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
118 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
119 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
120 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
121 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
122 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
123 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
124 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
125 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
126 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
127 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
128 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
129 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
130 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
131 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
132 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
133 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
134 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
135 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
136 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
139 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
140 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
141 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
142 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
143 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
144 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
145 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
146 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
147 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
148 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
149 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
150 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
151 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
152 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
153 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
154 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
155 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
156 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
157 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
158 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
159 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
160 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
161 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
162 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
163 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
164 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
165 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
166 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
167 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
168 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
169 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
170 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
171 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
172 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
173 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
174 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
175 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
176 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
177 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
178 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
179 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
180 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
181 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
182 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
183 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
184 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
185 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
186 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
187 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
188 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
189 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
190 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
191 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
192 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
193 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
194 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
195 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
196 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
197 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
198 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
199 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
200 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
201 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
202 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
203 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
204 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
205 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
208 static const struct print_architecture_table_node archi_table
[]= {
210 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
211 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
212 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
213 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
214 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
215 {"Windows IA64", SPL_ARCH_IA64
, 3 },
216 {"Windows x64", SPL_ARCH_X64
, 3 },
221 /****************************************************************************
222 generate a new TDB_DATA key for storing a printer
223 ****************************************************************************/
225 static TDB_DATA
make_printer_tdbkey(TALLOC_CTX
*ctx
, const char *sharename
)
231 fstrcpy(share
, sharename
);
234 keystr
= talloc_asprintf(ctx
, "%s%s", PRINTERS_PREFIX
, share
);
235 key
= string_term_tdb_data(keystr
? keystr
: "");
240 /****************************************************************************
241 generate a new TDB_DATA key for storing a printer security descriptor
242 ****************************************************************************/
244 static TDB_DATA
make_printers_secdesc_tdbkey(TALLOC_CTX
*ctx
,
245 const char* sharename
)
251 fstrcpy(share
, sharename
);
254 keystr
= talloc_asprintf(ctx
, "%s%s", SECDESC_PREFIX
, share
);
255 key
= string_term_tdb_data(keystr
? keystr
: "");
260 /****************************************************************************
261 ****************************************************************************/
263 static bool upgrade_to_version_3(void)
265 TDB_DATA kbuf
, newkey
, dbuf
;
267 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
269 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
270 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
272 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
274 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
275 DEBUG(0,("upgrade_to_version_3:moving form\n"));
276 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
277 SAFE_FREE(dbuf
.dptr
);
278 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
281 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
282 SAFE_FREE(dbuf
.dptr
);
283 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
288 if (strncmp((const char *)kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
289 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
290 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
291 SAFE_FREE(dbuf
.dptr
);
292 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
295 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
296 SAFE_FREE(dbuf
.dptr
);
297 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
302 if (strncmp((const char *)kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
303 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
304 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
305 SAFE_FREE(dbuf
.dptr
);
306 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
309 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
310 SAFE_FREE(dbuf
.dptr
);
311 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
316 SAFE_FREE(dbuf
.dptr
);
322 /*******************************************************************
323 Fix an issue with security descriptors. Printer sec_desc must
324 use more than the generic bits that were previously used
325 in <= 3.0.14a. They must also have a owner and group SID assigned.
326 Otherwise, any printers than have been migrated to a Windows
327 host using printmig.exe will not be accessible.
328 *******************************************************************/
330 static int sec_desc_upg_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
331 TDB_DATA data
, void *state
)
334 SEC_DESC_BUF
*sd_orig
= NULL
;
335 SEC_DESC_BUF
*sd_new
, *sd_store
;
336 SEC_DESC
*sec
, *new_sec
;
337 TALLOC_CTX
*ctx
= state
;
342 if (!data
.dptr
|| data
.dsize
== 0) {
346 if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 ) {
350 /* upgrade the security descriptor */
352 status
= unmarshall_sec_desc_buf(ctx
, data
.dptr
, data
.dsize
, &sd_orig
);
353 if (!NT_STATUS_IS_OK(status
)) {
354 /* delete bad entries */
355 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
356 (const char *)key
.dptr
));
357 tdb_delete( tdb_printers
, key
);
366 /* is this even valid? */
372 /* update access masks */
374 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
375 switch ( sec
->dacl
->aces
[i
].access_mask
) {
376 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
377 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_PRINT
;
380 case GENERIC_ALL_ACCESS
:
381 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_FULL_CONTROL
;
384 case READ_CONTROL_ACCESS
:
385 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
387 default: /* no change */
392 /* create a new SEC_DESC with the appropriate owner and group SIDs */
394 new_sec
= make_sec_desc( ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
395 &global_sid_Builtin_Administrators
,
396 &global_sid_Builtin_Administrators
,
397 NULL
, NULL
, &size_new_sec
);
401 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
406 if ( !(sd_store
= sec_desc_merge( ctx
, sd_new
, sd_orig
)) ) {
407 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
413 sd_size
= ndr_size_security_descriptor(sd_store
->sd
, NULL
, 0)
414 + sizeof(SEC_DESC_BUF
);
416 status
= marshall_sec_desc_buf(ctx
, sd_store
, &data
.dptr
, &data
.dsize
);
417 if (!NT_STATUS_IS_OK(status
)) {
418 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
422 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
424 /* 0 to continue and non-zero to stop traversal */
426 return (result
== -1);
429 /*******************************************************************
430 *******************************************************************/
432 static bool upgrade_to_version_4(void)
437 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
439 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
442 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
444 talloc_destroy( ctx
);
446 return ( result
!= -1 );
449 /*******************************************************************
450 Fix an issue with security descriptors. Printer sec_desc must
451 use more than the generic bits that were previously used
452 in <= 3.0.14a. They must also have a owner and group SID assigned.
453 Otherwise, any printers than have been migrated to a Windows
454 host using printmig.exe will not be accessible.
455 *******************************************************************/
457 static int normalize_printers_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
458 TDB_DATA data
, void *state
)
460 TALLOC_CTX
*ctx
= talloc_tos();
463 if (!data
.dptr
|| data
.dsize
== 0)
466 /* upgrade printer records and security descriptors */
468 if ( strncmp((const char *) key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
469 new_key
= make_printer_tdbkey(ctx
, (const char *)key
.dptr
+strlen(PRINTERS_PREFIX
) );
471 else if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
472 new_key
= make_printers_secdesc_tdbkey(ctx
, (const char *)key
.dptr
+strlen(SECDESC_PREFIX
) );
475 /* ignore this record */
479 /* delete the original record and store under the normalized key */
481 if ( tdb_delete( the_tdb
, key
) != 0 ) {
482 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
487 if ( tdb_store( the_tdb
, new_key
, data
, TDB_REPLACE
) != 0 ) {
488 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
496 /*******************************************************************
497 *******************************************************************/
499 static bool upgrade_to_version_5(void)
504 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
506 if ( !(ctx
= talloc_init( "upgrade_to_version_5" )) )
509 result
= tdb_traverse( tdb_printers
, normalize_printers_fn
, NULL
);
511 talloc_destroy( ctx
);
513 return ( result
!= -1 );
516 /****************************************************************************
517 Open the NT printing tdbs. Done once before fork().
518 ****************************************************************************/
520 bool nt_printing_init(struct messaging_context
*msg_ctx
)
522 const char *vstring
= "INFO/version";
526 if ( tdb_drivers
&& tdb_printers
&& tdb_forms
)
530 tdb_close(tdb_drivers
);
531 tdb_drivers
= tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
533 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
534 state_path("ntdrivers.tdb"), strerror(errno
) ));
539 tdb_close(tdb_printers
);
540 tdb_printers
= tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
542 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
543 state_path("ntprinters.tdb"), strerror(errno
) ));
548 tdb_close(tdb_forms
);
549 tdb_forms
= tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
551 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
552 state_path("ntforms.tdb"), strerror(errno
) ));
556 /* handle a Samba upgrade */
558 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
560 DEBUG(10, ("Fresh database\n"));
561 tdb_store_int32( tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
562 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
565 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
567 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
568 if (!upgrade_to_version_3())
570 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
571 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
574 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
575 /* Written on a bigendian machine with old fetch_int code. Save as le. */
576 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
577 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
578 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
581 if (vers_id
== NTDRIVERS_DATABASE_VERSION_3
) {
582 if ( !upgrade_to_version_4() )
584 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_4
);
585 vers_id
= NTDRIVERS_DATABASE_VERSION_4
;
588 if (vers_id
== NTDRIVERS_DATABASE_VERSION_4
) {
589 if ( !upgrade_to_version_5() )
591 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
592 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
596 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
597 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id
));
602 update_c_setprinter(True
);
605 * register callback to handle updating printers as new
606 * drivers are installed
609 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
610 do_drv_upgrade_printer
);
613 * register callback to handle updating printer data
614 * when a driver is initialized
617 messaging_register(msg_ctx
, NULL
, MSG_PRINTERDATA_INIT_RESET
,
618 reset_all_printerdata
);
620 /* of course, none of the message callbacks matter if you don't
621 tell messages.c that you interested in receiving PRINT_GENERAL
622 msgs. This is done in claim_connection() */
625 if ( lp_security() == SEC_ADS
) {
626 win_rc
= check_published_printers();
627 if (!W_ERROR_IS_OK(win_rc
))
628 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
634 /*******************************************************************
635 Function to allow filename parsing "the old way".
636 ********************************************************************/
638 NTSTATUS
driver_unix_convert(connection_struct
*conn
,
639 const char *old_name
,
640 struct smb_filename
**smb_fname
)
643 TALLOC_CTX
*ctx
= talloc_tos();
644 char *name
= talloc_strdup(ctx
, old_name
);
647 return NT_STATUS_NO_MEMORY
;
650 name
= unix_clean_name(ctx
, name
);
652 return NT_STATUS_NO_MEMORY
;
654 trim_string(name
,"/","/");
656 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
657 if (!NT_STATUS_IS_OK(status
)) {
658 return NT_STATUS_NO_MEMORY
;
664 /*******************************************************************
665 tdb traversal function for counting printers.
666 ********************************************************************/
668 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
669 TDB_DATA data
, void *context
)
671 int *printer_count
= (int*)context
;
673 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
675 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
681 /*******************************************************************
682 Update the spooler global c_setprinter. This variable is initialized
683 when the parent smbd starts with the number of existing printers. It
684 is monotonically increased by the current number of printers *after*
685 each add or delete printer RPC. Only Microsoft knows why... JRR020119
686 ********************************************************************/
688 uint32
update_c_setprinter(bool initialize
)
691 int32 printer_count
= 0;
693 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
695 /* Traverse the tdb, counting the printers */
696 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
698 /* If initializing, set c_setprinter to current printers count
699 * otherwise, bump it by the current printer count
702 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
704 c_setprinter
= printer_count
;
706 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
707 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
709 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
711 return (uint32
)c_setprinter
;
714 /*******************************************************************
715 Get the spooler global c_setprinter, accounting for initialization.
716 ********************************************************************/
718 uint32
get_c_setprinter(void)
720 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
722 if (c_setprinter
== (int32
)-1)
723 c_setprinter
= update_c_setprinter(True
);
725 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
727 return (uint32
)c_setprinter
;
730 /****************************************************************************
731 Get builtin form struct list.
732 ****************************************************************************/
734 int get_builtin_ntforms(nt_forms_struct
**list
)
736 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
740 return ARRAY_SIZE(default_forms
);
743 /****************************************************************************
744 get a builtin form struct
745 ****************************************************************************/
747 bool get_a_builtin_ntform_by_string(const char *form_name
, nt_forms_struct
*form
)
750 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
751 for (i
=0; i
<ARRAY_SIZE(default_forms
); i
++) {
752 if (strequal(form_name
,default_forms
[i
].name
)) {
753 DEBUGADD(6,("Found builtin form %s \n", form_name
));
754 memcpy(form
,&default_forms
[i
],sizeof(*form
));
762 /****************************************************************************
763 get a form struct list.
764 ****************************************************************************/
766 int get_ntforms(nt_forms_struct
**list
)
768 TDB_DATA kbuf
, newkey
, dbuf
;
769 nt_forms_struct form
;
776 for (kbuf
= tdb_firstkey(tdb_forms
);
778 newkey
= tdb_nextkey(tdb_forms
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
)
780 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
783 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
787 fstrcpy(form
.name
, (const char *)kbuf
.dptr
+strlen(FORMS_PREFIX
));
788 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
789 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
790 &form
.top
, &form
.right
, &form
.bottom
);
791 SAFE_FREE(dbuf
.dptr
);
792 if (ret
!= dbuf
.dsize
)
795 *list
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
797 DEBUG(0,("get_ntforms: Realloc fail.\n"));
808 /****************************************************************************
809 write a form struct list
810 ****************************************************************************/
812 int write_ntforms(nt_forms_struct
**list
, int number
)
814 TALLOC_CTX
*ctx
= talloc_tos();
821 for (i
=0;i
<number
;i
++) {
822 /* save index, so list is rebuilt in correct order */
823 len
= tdb_pack(NULL
, 0, "dddddddd",
824 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
825 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
830 buf
= TALLOC_ARRAY(ctx
, char, len
);
834 len
= tdb_pack((uint8
*)buf
, len
, "dddddddd",
835 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
836 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
838 key
= talloc_asprintf(ctx
, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
843 dbuf
.dptr
= (uint8
*)buf
;
844 if (tdb_store_bystring(tdb_forms
, key
, dbuf
, TDB_REPLACE
) != 0) {
856 /****************************************************************************
857 add a form struct at the end of the list
858 ****************************************************************************/
859 bool add_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int *count
)
865 * NT tries to add forms even when
866 * they are already in the base
867 * only update the values if already present
872 for (n
=0; n
<*count
; n
++) {
873 if ( strequal((*list
)[n
].name
, form
->form_name
) ) {
880 if((*list
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
881 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
884 fstrcpy((*list
)[n
].name
, form
->form_name
);
888 (*list
)[n
].flag
= form
->flags
;
889 (*list
)[n
].width
= form
->size
.width
;
890 (*list
)[n
].length
= form
->size
.height
;
891 (*list
)[n
].left
= form
->area
.left
;
892 (*list
)[n
].top
= form
->area
.top
;
893 (*list
)[n
].right
= form
->area
.right
;
894 (*list
)[n
].bottom
= form
->area
.bottom
;
896 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
897 update
? "updated" : "added", form
->form_name
));
902 /****************************************************************************
903 Delete a named form struct.
904 ****************************************************************************/
906 bool delete_a_form(nt_forms_struct
**list
, const char *del_name
, int *count
, WERROR
*ret
)
913 for (n
=0; n
<*count
; n
++) {
914 if (!strncmp((*list
)[n
].name
, del_name
, strlen(del_name
))) {
915 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name
));
921 DEBUG(10,("delete_a_form, [%s] not found\n", del_name
));
922 *ret
= WERR_INVALID_PARAM
;
926 if (asprintf(&key
, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
) < 0) {
930 if (tdb_delete_bystring(tdb_forms
, key
) != 0) {
939 /****************************************************************************
940 Update a form struct.
941 ****************************************************************************/
943 void update_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int count
)
947 DEBUG(106, ("[%s]\n", form
->form_name
));
948 for (n
=0; n
<count
; n
++) {
949 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
950 if (!strncmp((*list
)[n
].name
, form
->form_name
, strlen(form
->form_name
)))
954 if (n
==count
) return;
956 (*list
)[n
].flag
= form
->flags
;
957 (*list
)[n
].width
= form
->size
.width
;
958 (*list
)[n
].length
= form
->size
.height
;
959 (*list
)[n
].left
= form
->area
.left
;
960 (*list
)[n
].top
= form
->area
.top
;
961 (*list
)[n
].right
= form
->area
.right
;
962 (*list
)[n
].bottom
= form
->area
.bottom
;
965 /****************************************************************************
966 Get the nt drivers list.
967 Traverse the database and look-up the matching names.
968 ****************************************************************************/
969 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
972 const char *short_archi
;
974 TDB_DATA kbuf
, newkey
;
976 short_archi
= get_short_archi(architecture
);
981 if (asprintf(&key
, "%s%s/%d/", DRIVERS_PREFIX
,
982 short_archi
, version
) < 0) {
986 if (asprintf(&key8
, "%s%s/%d/", DRIVERS_PREFIX8
,
987 short_archi
, version
) < 0) {
992 for (kbuf
= tdb_firstkey(tdb_drivers
);
994 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
996 if ((strncmp((const char *)kbuf
.dptr
, key
, strlen(key
)) == 0) ||
997 (strncmp((const char *)kbuf
.dptr
, key8
, strlen(key8
)) == 0)) {
999 if((*list
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
1000 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1006 if (strncmp((const char *)kbuf
.dptr
, key
, strlen(key
)) == 0) {
1007 fstrcpy((*list
)[total
], (const char *)kbuf
.dptr
+strlen(key
));
1008 } else if (strncmp((const char *)kbuf
.dptr
, key8
, strlen(key8
)) == 0) {
1009 fstrcpy((*list
)[total
], (const char *)kbuf
.dptr
+strlen(key8
));
1023 /****************************************************************************
1024 Function to do the mapping between the long architecture name and
1026 ****************************************************************************/
1028 const char *get_short_archi(const char *long_archi
)
1032 DEBUG(107,("Getting architecture dependant directory\n"));
1035 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
1036 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
1038 if (archi_table
[i
].long_archi
==NULL
) {
1039 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
1043 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1045 DEBUGADD(108,("index: [%d]\n", i
));
1046 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
1047 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
1049 return archi_table
[i
].short_archi
;
1052 /****************************************************************************
1053 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1054 There are two case to be covered here: PE (Portable Executable) and NE (New
1055 Executable) files. Both files support the same INFO structure, but PE files
1056 store the signature in unicode, and NE files store it as !unicode.
1057 returns -1 on error, 1 on version info found, and 0 on no version info found.
1058 ****************************************************************************/
1060 int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1066 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
1067 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1068 fname
, DOS_HEADER_SIZE
));
1072 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1073 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1074 fname
, (unsigned long)byte_count
));
1075 goto no_version_info
;
1078 /* Is this really a DOS header? */
1079 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1080 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1081 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1082 goto no_version_info
;
1085 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1086 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1087 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1089 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1090 goto no_version_info
;
1093 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1094 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
1095 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1096 fname
, (unsigned long)byte_count
));
1097 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1098 goto no_version_info
;
1101 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1102 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1103 unsigned int num_sections
;
1104 unsigned int section_table_bytes
;
1106 /* Just skip over optional header to get to section table */
1107 if (SMB_VFS_LSEEK(fsp
,
1108 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
1109 SEEK_CUR
) == (SMB_OFF_T
)-1) {
1110 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1115 /* get the section table */
1116 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1117 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1118 if (section_table_bytes
== 0)
1122 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
1123 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1124 fname
, section_table_bytes
));
1128 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1129 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1130 fname
, (unsigned long)byte_count
));
1134 /* Iterate the section table looking for the resource section ".rsrc" */
1135 for (i
= 0; i
< num_sections
; i
++) {
1136 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1138 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1139 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1140 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1142 if (section_bytes
== 0)
1146 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
1147 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1148 fname
, section_bytes
));
1152 /* Seek to the start of the .rsrc section info */
1153 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1154 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1159 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1160 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1161 fname
, (unsigned long)byte_count
));
1165 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1168 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1169 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1170 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1171 /* Align to next long address */
1172 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1174 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1175 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1176 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1178 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1179 fname
, *major
, *minor
,
1180 (*major
>>16)&0xffff, *major
&0xffff,
1181 (*minor
>>16)&0xffff, *minor
&0xffff));
1190 /* Version info not found, fall back to origin date/time */
1191 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1195 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1196 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1197 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1198 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1199 /* At this point, we assume the file is in error. It still could be somthing
1200 * else besides a NE file, but it unlikely at this point. */
1204 /* Allocate a bit more space to speed up things */
1206 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1207 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1208 fname
, PE_HEADER_SIZE
));
1212 /* This is a HACK! I got tired of trying to sort through the messy
1213 * 'NE' file format. If anyone wants to clean this up please have at
1214 * it, but this works. 'NE' files will eventually fade away. JRR */
1215 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1216 /* Cover case that should not occur in a well formed 'NE' .dll file */
1217 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1219 for(i
=0; i
<byte_count
; i
++) {
1220 /* Fast skip past data that can't possibly match */
1221 if (buf
[i
] != 'V') continue;
1223 /* Potential match data crosses buf boundry, move it to beginning
1224 * of buf, and fill the buf with as much as it will hold. */
1225 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1228 memcpy(buf
, &buf
[i
], byte_count
-i
);
1229 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1230 (byte_count
-i
))) < 0) {
1232 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1237 byte_count
= bc
+ (byte_count
- i
);
1238 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1243 /* Check that the full signature string and the magic number that
1244 * follows exist (not a perfect solution, but the chances that this
1245 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1246 * twice, as it is simpler to read the code. */
1247 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1248 /* Compute skip alignment to next long address */
1249 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
1250 sizeof(VS_SIGNATURE
)) & 3;
1251 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1253 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1254 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1255 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1256 fname
, *major
, *minor
,
1257 (*major
>>16)&0xffff, *major
&0xffff,
1258 (*minor
>>16)&0xffff, *minor
&0xffff));
1265 /* Version info not found, fall back to origin date/time */
1266 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1271 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1272 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1273 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1284 /****************************************************************************
1285 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1286 share one or more files. During the MS installation process files are checked
1287 to insure that only a newer version of a shared file is installed over an
1288 older version. There are several possibilities for this comparison. If there
1289 is no previous version, the new one is newer (obviously). If either file is
1290 missing the version info structure, compare the creation date (on Unix use
1291 the modification date). Otherwise chose the numerically larger version number.
1292 ****************************************************************************/
1294 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1296 bool use_version
= true;
1300 time_t new_create_time
;
1304 time_t old_create_time
;
1306 struct smb_filename
*smb_fname
= NULL
;
1307 files_struct
*fsp
= NULL
;
1313 SET_STAT_INVALID(st
);
1314 new_create_time
= (time_t)0;
1315 old_create_time
= (time_t)0;
1317 /* Get file version info (if available) for previous file (if it exists) */
1318 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
1319 if (!NT_STATUS_IS_OK(status
)) {
1323 status
= SMB_VFS_CREATE_FILE(
1326 0, /* root_dir_fid */
1327 smb_fname
, /* fname */
1328 FILE_GENERIC_READ
, /* access_mask */
1329 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1330 FILE_OPEN
, /* create_disposition*/
1331 0, /* create_options */
1332 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1333 INTERNAL_OPEN_ONLY
, /* oplock_request */
1334 0, /* allocation_size */
1340 if (!NT_STATUS_IS_OK(status
)) {
1341 /* Old file not found, so by definition new file is in fact newer */
1342 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1343 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
1349 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1355 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1357 use_version
= false;
1358 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1361 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1362 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1363 (long)old_create_time
));
1366 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1369 /* Get file version info (if available) for new file */
1370 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
1371 if (!NT_STATUS_IS_OK(status
)) {
1375 status
= SMB_VFS_CREATE_FILE(
1378 0, /* root_dir_fid */
1379 smb_fname
, /* fname */
1380 FILE_GENERIC_READ
, /* access_mask */
1381 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1382 FILE_OPEN
, /* create_disposition*/
1383 0, /* create_options */
1384 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1385 INTERNAL_OPEN_ONLY
, /* oplock_request */
1386 0, /* allocation_size */
1392 if (!NT_STATUS_IS_OK(status
)) {
1393 /* New file not found, this shouldn't occur if the caller did its job */
1394 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1395 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
1399 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1405 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1407 use_version
= false;
1408 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1411 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1412 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1413 (long)new_create_time
));
1416 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1419 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1420 /* Compare versions and choose the larger version number */
1421 if (new_major
> old_major
||
1422 (new_major
== old_major
&& new_minor
> old_minor
)) {
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
));
1435 /* Compare modification time/dates and choose the newest time/date */
1436 if (new_create_time
> old_create_time
) {
1437 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1442 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1450 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1453 TALLOC_FREE(smb_fname
);
1457 /****************************************************************************
1458 Determine the correct cVersion associated with an architecture and driver
1459 ****************************************************************************/
1460 static uint32
get_correct_cversion(struct pipes_struct
*p
,
1461 const char *architecture
,
1462 const char *driverpath_in
,
1467 struct smb_filename
*smb_fname
= NULL
;
1468 char *driverpath
= NULL
;
1469 files_struct
*fsp
= NULL
;
1470 connection_struct
*conn
= NULL
;
1473 fstring printdollar
;
1474 int printdollar_snum
;
1476 *perr
= WERR_INVALID_PARAM
;
1478 /* If architecture is Windows 95/98/ME, the version is always 0. */
1479 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1480 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1485 /* If architecture is Windows x64, the version is always 3. */
1486 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1487 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1492 fstrcpy(printdollar
, "print$");
1494 printdollar_snum
= find_service(printdollar
);
1495 if (printdollar_snum
== -1) {
1496 *perr
= WERR_NO_SUCH_SHARE
;
1500 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1501 lp_pathname(printdollar_snum
),
1502 p
->server_info
, &oldcwd
);
1503 if (!NT_STATUS_IS_OK(nt_status
)) {
1504 DEBUG(0,("get_correct_cversion: create_conn_struct "
1505 "returned %s\n", nt_errstr(nt_status
)));
1506 *perr
= ntstatus_to_werror(nt_status
);
1510 /* Open the driver file (Portable Executable format) and determine the
1511 * deriver the cversion. */
1512 driverpath
= talloc_asprintf(talloc_tos(),
1521 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
1522 if (!NT_STATUS_IS_OK(nt_status
)) {
1523 *perr
= ntstatus_to_werror(nt_status
);
1527 nt_status
= vfs_file_exist(conn
, smb_fname
);
1528 if (!NT_STATUS_IS_OK(nt_status
)) {
1529 *perr
= WERR_BADFILE
;
1533 status
= SMB_VFS_CREATE_FILE(
1536 0, /* root_dir_fid */
1537 smb_fname
, /* fname */
1538 FILE_GENERIC_READ
, /* access_mask */
1539 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1540 FILE_OPEN
, /* create_disposition*/
1541 0, /* create_options */
1542 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1543 INTERNAL_OPEN_ONLY
, /* oplock_request */
1544 0, /* allocation_size */
1550 if (!NT_STATUS_IS_OK(status
)) {
1551 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1552 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
1553 *perr
= WERR_ACCESS_DENIED
;
1560 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
1561 if (ret
== -1) goto error_exit
;
1564 DEBUG(6,("get_correct_cversion: Version info not "
1566 smb_fname_str_dbg(smb_fname
)));
1571 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1572 * for more details. Version in this case is not just the version of the
1573 * file, but the version in the sense of kernal mode (2) vs. user mode
1574 * (3) drivers. Other bits of the version fields are the version info.
1577 cversion
= major
& 0x0000ffff;
1579 case 2: /* WinNT drivers */
1580 case 3: /* Win2K drivers */
1584 DEBUG(6,("get_correct_cversion: cversion "
1585 "invalid [%s] cversion = %d\n",
1586 smb_fname_str_dbg(smb_fname
),
1591 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1592 " = 0x%x minor = 0x%x\n",
1593 smb_fname_str_dbg(smb_fname
), major
, minor
));
1596 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1597 smb_fname_str_dbg(smb_fname
), cversion
));
1604 TALLOC_FREE(smb_fname
);
1606 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1609 vfs_ChDir(conn
, oldcwd
);
1612 if (cversion
!= -1) {
1618 /****************************************************************************
1619 ****************************************************************************/
1621 #define strip_driver_path(_mem_ctx, _element) do { \
1622 if ((_p = strrchr((_element), '\\')) != NULL) { \
1623 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1624 W_ERROR_HAVE_NO_MEMORY((_element)); \
1628 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
1629 struct pipes_struct
*rpc_pipe
,
1630 const char *architecture
,
1631 const char **driver_path
,
1632 const char **data_file
,
1633 const char **config_file
,
1634 const char **help_file
,
1635 struct spoolss_StringArray
*dependent_files
,
1638 const char *short_architecture
;
1643 /* clean up the driver name.
1644 * we can get .\driver.dll
1645 * or worse c:\windows\system\driver.dll !
1647 /* using an intermediate string to not have overlaping memcpy()'s */
1649 strip_driver_path(mem_ctx
, *driver_path
);
1650 strip_driver_path(mem_ctx
, *data_file
);
1651 strip_driver_path(mem_ctx
, *config_file
);
1652 strip_driver_path(mem_ctx
, *help_file
);
1654 if (dependent_files
&& dependent_files
->string
) {
1655 for (i
=0; dependent_files
->string
[i
]; i
++) {
1656 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
1660 short_architecture
= get_short_archi(architecture
);
1661 if (!short_architecture
) {
1662 return WERR_UNKNOWN_PRINTER_DRIVER
;
1665 /* jfm:7/16/2000 the client always sends the cversion=0.
1666 * The server should check which version the driver is by reading
1667 * the PE header of driver->driverpath.
1669 * For Windows 95/98 the version is 0 (so the value sent is correct)
1670 * For Windows NT (the architecture doesn't matter)
1671 * NT 3.1: cversion=0
1672 * NT 3.5/3.51: cversion=1
1677 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
1678 *driver_path
, &err
);
1679 if (*version
== -1) {
1686 /****************************************************************************
1687 ****************************************************************************/
1689 WERROR
clean_up_driver_struct(struct pipes_struct
*rpc_pipe
,
1690 struct spoolss_AddDriverInfoCtr
*r
)
1694 return clean_up_driver_struct_level(r
, rpc_pipe
,
1695 r
->info
.info3
->architecture
,
1696 &r
->info
.info3
->driver_path
,
1697 &r
->info
.info3
->data_file
,
1698 &r
->info
.info3
->config_file
,
1699 &r
->info
.info3
->help_file
,
1700 r
->info
.info3
->dependent_files
,
1701 &r
->info
.info3
->version
);
1703 return clean_up_driver_struct_level(r
, rpc_pipe
,
1704 r
->info
.info6
->architecture
,
1705 &r
->info
.info6
->driver_path
,
1706 &r
->info
.info6
->data_file
,
1707 &r
->info
.info6
->config_file
,
1708 &r
->info
.info6
->help_file
,
1709 r
->info
.info6
->dependent_files
,
1710 &r
->info
.info6
->version
);
1712 return clean_up_driver_struct_level(r
, rpc_pipe
,
1713 r
->info
.info8
->architecture
,
1714 &r
->info
.info8
->driver_path
,
1715 &r
->info
.info8
->data_file
,
1716 &r
->info
.info8
->config_file
,
1717 &r
->info
.info8
->help_file
,
1718 r
->info
.info8
->dependent_files
,
1719 &r
->info
.info8
->version
);
1721 return WERR_NOT_SUPPORTED
;
1725 /****************************************************************************
1726 This function sucks and should be replaced. JRA.
1727 ****************************************************************************/
1729 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1730 const struct spoolss_AddDriverInfo6
*src
)
1732 dst
->version
= src
->version
;
1734 dst
->driver_name
= src
->driver_name
;
1735 dst
->architecture
= src
->architecture
;
1736 dst
->driver_path
= src
->driver_path
;
1737 dst
->data_file
= src
->data_file
;
1738 dst
->config_file
= src
->config_file
;
1739 dst
->help_file
= src
->help_file
;
1740 dst
->monitor_name
= src
->monitor_name
;
1741 dst
->default_datatype
= src
->default_datatype
;
1742 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1743 dst
->dependent_files
= src
->dependent_files
;
1746 /****************************************************************************
1747 This function sucks and should be replaced. JRA.
1748 ****************************************************************************/
1750 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1751 const struct spoolss_AddDriverInfo8
*src
)
1753 dst
->version
= src
->version
;
1755 dst
->driver_name
= src
->driver_name
;
1756 dst
->architecture
= src
->architecture
;
1757 dst
->driver_path
= src
->driver_path
;
1758 dst
->data_file
= src
->data_file
;
1759 dst
->config_file
= src
->config_file
;
1760 dst
->help_file
= src
->help_file
;
1761 dst
->monitor_name
= src
->monitor_name
;
1762 dst
->default_datatype
= src
->default_datatype
;
1763 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1764 dst
->dependent_files
= src
->dependent_files
;
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
1771 connection_struct
*conn
,
1772 const char *driver_file
,
1773 const char *short_architecture
,
1774 uint32_t driver_version
,
1777 struct smb_filename
*smb_fname_old
= NULL
;
1778 struct smb_filename
*smb_fname_new
= NULL
;
1779 char *old_name
= NULL
;
1780 char *new_name
= NULL
;
1784 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
1785 short_architecture
, driver_file
);
1786 W_ERROR_HAVE_NO_MEMORY(old_name
);
1788 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
1789 short_architecture
, driver_version
, driver_file
);
1790 if (new_name
== NULL
) {
1791 TALLOC_FREE(old_name
);
1795 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
1797 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
1798 if (!NT_STATUS_IS_OK(status
)) {
1803 /* Setup a synthetic smb_filename struct */
1804 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
1805 if (!smb_fname_new
) {
1810 smb_fname_new
->base_name
= new_name
;
1812 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1813 "'%s'\n", smb_fname_old
->base_name
,
1814 smb_fname_new
->base_name
));
1816 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
1817 OPENX_FILE_EXISTS_TRUNCATE
|
1818 OPENX_FILE_CREATE_IF_NOT_EXIST
,
1821 if (!NT_STATUS_IS_OK(status
)) {
1822 DEBUG(0,("move_driver_file_to_download_area: Unable "
1823 "to rename [%s] to [%s]: %s\n",
1824 smb_fname_old
->base_name
, new_name
,
1825 nt_errstr(status
)));
1826 ret
= WERR_ACCESS_DENIED
;
1833 TALLOC_FREE(smb_fname_old
);
1834 TALLOC_FREE(smb_fname_new
);
1838 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
1839 struct spoolss_AddDriverInfoCtr
*r
,
1842 struct spoolss_AddDriverInfo3
*driver
;
1843 struct spoolss_AddDriverInfo3 converted_driver
;
1844 const char *short_architecture
;
1845 struct smb_filename
*smb_dname
= NULL
;
1846 char *new_dir
= NULL
;
1847 connection_struct
*conn
= NULL
;
1850 TALLOC_CTX
*ctx
= talloc_tos();
1853 fstring printdollar
;
1854 int printdollar_snum
;
1860 driver
= r
->info
.info3
;
1863 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
1864 driver
= &converted_driver
;
1867 convert_level_8_to_level3(&converted_driver
, r
->info
.info8
);
1868 driver
= &converted_driver
;
1871 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
1872 return WERR_UNKNOWN_LEVEL
;
1875 short_architecture
= get_short_archi(driver
->architecture
);
1876 if (!short_architecture
) {
1877 return WERR_UNKNOWN_PRINTER_DRIVER
;
1880 fstrcpy(printdollar
, "print$");
1882 printdollar_snum
= find_service(printdollar
);
1883 if (printdollar_snum
== -1) {
1884 *perr
= WERR_NO_SUCH_SHARE
;
1885 return WERR_NO_SUCH_SHARE
;
1888 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1889 lp_pathname(printdollar_snum
),
1890 p
->server_info
, &oldcwd
);
1891 if (!NT_STATUS_IS_OK(nt_status
)) {
1892 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1893 "returned %s\n", nt_errstr(nt_status
)));
1894 *perr
= ntstatus_to_werror(nt_status
);
1898 new_dir
= talloc_asprintf(ctx
,
1906 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1907 if (!NT_STATUS_IS_OK(nt_status
)) {
1912 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1914 create_directory(conn
, NULL
, smb_dname
);
1916 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1917 * listed for this driver which has already been moved, skip it (note:
1918 * drivers may list the same file name several times. Then check if the
1919 * file already exists in archi\version\, if so, check that the version
1920 * info (or time stamps if version info is unavailable) is newer (or the
1921 * date is later). If it is, move it to archi\version\filexxx.yyy.
1922 * Otherwise, delete the file.
1924 * If a file is not moved to archi\version\ because of an error, all the
1925 * rest of the 'unmoved' driver files are removed from archi\. If one or
1926 * more of the driver's files was already moved to archi\version\, it
1927 * potentially leaves the driver in a partially updated state. Version
1928 * trauma will most likely occur if an client attempts to use any printer
1929 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1930 * done is appropriate... later JRR
1933 DEBUG(5,("Moving files now !\n"));
1935 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1937 *perr
= move_driver_file_to_download_area(ctx
,
1939 driver
->driver_path
,
1943 if (!W_ERROR_IS_OK(*perr
)) {
1944 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1951 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1952 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1954 *perr
= move_driver_file_to_download_area(ctx
,
1960 if (!W_ERROR_IS_OK(*perr
)) {
1961 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1969 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1970 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1971 !strequal(driver
->config_file
, driver
->data_file
)) {
1973 *perr
= move_driver_file_to_download_area(ctx
,
1975 driver
->config_file
,
1979 if (!W_ERROR_IS_OK(*perr
)) {
1980 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1988 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1989 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1990 !strequal(driver
->help_file
, driver
->data_file
) &&
1991 !strequal(driver
->help_file
, driver
->config_file
)) {
1993 *perr
= move_driver_file_to_download_area(ctx
,
1999 if (!W_ERROR_IS_OK(*perr
)) {
2000 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
2008 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
2009 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
2010 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
2011 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
2012 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
2013 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
2015 for (j
=0; j
< i
; j
++) {
2016 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
2021 *perr
= move_driver_file_to_download_area(ctx
,
2023 driver
->dependent_files
->string
[i
],
2027 if (!W_ERROR_IS_OK(*perr
)) {
2028 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
2039 TALLOC_FREE(smb_dname
);
2042 vfs_ChDir(conn
, oldcwd
);
2046 if (W_ERROR_EQUAL(*perr
, WERR_OK
)) {
2050 return WERR_UNKNOWN_PRINTER_DRIVER
;
2055 /****************************************************************************
2056 ****************************************************************************/
2058 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8
*r
)
2060 TALLOC_CTX
*ctx
= talloc_tos();
2061 const char *architecture
;
2062 char *directory
= NULL
;
2066 enum ndr_err_code ndr_err
;
2069 architecture
= get_short_archi(r
->architecture
);
2070 if (!architecture
) {
2071 return (uint32_t)-1;
2074 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2075 * \\server is added in the rpc server layer.
2076 * It does make sense to NOT store the server's name in the printer TDB.
2079 directory
= talloc_asprintf(ctx
, "\\print$\\%s\\%d\\",
2080 architecture
, r
->version
);
2082 return (uint32_t)-1;
2085 #define gen_full_driver_unc_path(ctx, directory, file) \
2087 if (file && strlen(file)) { \
2088 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2090 file = talloc_strdup(ctx, ""); \
2093 return (uint32_t)-1; \
2097 /* .inf files do not always list a file for each of the four standard files.
2098 * Don't prepend a path to a null filename, or client claims:
2099 * "The server on which the printer resides does not have a suitable
2100 * <printer driver name> printer driver installed. Click OK if you
2101 * wish to install the driver on your local machine."
2103 gen_full_driver_unc_path(ctx
, directory
, r
->driver_path
);
2104 gen_full_driver_unc_path(ctx
, directory
, r
->data_file
);
2105 gen_full_driver_unc_path(ctx
, directory
, r
->config_file
);
2106 gen_full_driver_unc_path(ctx
, directory
, r
->help_file
);
2108 for (i
=0; r
->dependent_files
&& r
->dependent_files
[i
]; i
++) {
2109 gen_full_driver_unc_path(ctx
, directory
,
2110 r
->dependent_files
[i
]);
2113 key
= talloc_asprintf(ctx
, "%s%s/%d/%s", DRIVERS_PREFIX8
,
2114 architecture
, r
->version
, r
->driver_name
);
2116 return (uint32_t)-1;
2119 DEBUG(5,("add_a_printer_driver_8: Adding driver with key %s\n", key
));
2121 ndr_err
= ndr_push_struct_blob(&blob
, ctx
, NULL
, r
,
2122 (ndr_push_flags_fn_t
)ndr_push_spoolss_DriverInfo8
);
2123 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2124 return (uint32_t)-1;
2127 dbuf
.dptr
= blob
.data
;
2128 dbuf
.dsize
= blob
.length
;
2130 ret
= tdb_store_bystring(tdb_drivers
, key
, dbuf
, TDB_REPLACE
);
2132 data_blob_free(&blob
);
2135 DEBUG(0,("add_a_printer_driver_8: Adding driver with key %s failed.\n", key
));
2141 /****************************************************************************
2142 ****************************************************************************/
2144 static WERROR
get_a_printer_driver_3_default(TALLOC_CTX
*mem_ctx
,
2145 struct spoolss_DriverInfo3
*info
,
2146 const char *driver
, const char *arch
)
2148 info
->driver_name
= talloc_strdup(mem_ctx
, driver
);
2149 if (!info
->driver_name
) {
2153 info
->default_datatype
= talloc_strdup(mem_ctx
, "RAW");
2154 if (!info
->default_datatype
) {
2158 info
->driver_path
= talloc_strdup(mem_ctx
, "");
2159 info
->data_file
= talloc_strdup(mem_ctx
, "");
2160 info
->config_file
= talloc_strdup(mem_ctx
, "");
2161 info
->help_file
= talloc_strdup(mem_ctx
, "");
2162 if (!info
->driver_path
|| !info
->data_file
|| !info
->config_file
|| !info
->help_file
) {
2169 /****************************************************************************
2170 ****************************************************************************/
2172 static WERROR
get_a_printer_driver_3(TALLOC_CTX
*mem_ctx
,
2173 struct spoolss_DriverInfo3
*driver
,
2174 const char *drivername
, const char *arch
,
2178 const char *architecture
;
2182 fstring name
, driverpath
, environment
, datafile
, configfile
, helpfile
, monitorname
, defaultdatatype
;
2184 architecture
= get_short_archi(arch
);
2185 if ( !architecture
) {
2186 return WERR_UNKNOWN_PRINTER_DRIVER
;
2189 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2191 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2194 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2196 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
2197 architecture
, version
, drivername
) < 0) {
2201 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
2204 return WERR_UNKNOWN_PRINTER_DRIVER
;
2207 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2218 driver
->driver_name
= talloc_strdup(mem_ctx
, name
);
2219 driver
->architecture
= talloc_strdup(mem_ctx
, environment
);
2220 driver
->driver_path
= talloc_strdup(mem_ctx
, driverpath
);
2221 driver
->data_file
= talloc_strdup(mem_ctx
, datafile
);
2222 driver
->config_file
= talloc_strdup(mem_ctx
, configfile
);
2223 driver
->help_file
= talloc_strdup(mem_ctx
, helpfile
);
2224 driver
->monitor_name
= talloc_strdup(mem_ctx
, monitorname
);
2225 driver
->default_datatype
= talloc_strdup(mem_ctx
, defaultdatatype
);
2229 while (len
< dbuf
.dsize
) {
2233 driver
->dependent_files
= talloc_realloc(mem_ctx
, driver
->dependent_files
, const char *, i
+2);
2234 if (!driver
->dependent_files
) {
2235 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2239 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2242 driver
->dependent_files
[i
] = talloc_strdup(mem_ctx
, file
);
2247 if (driver
->dependent_files
)
2248 driver
->dependent_files
[i
] = NULL
;
2250 SAFE_FREE(dbuf
.dptr
);
2253 if (len
!= dbuf
.dsize
) {
2254 return get_a_printer_driver_3_default(mem_ctx
, driver
, drivername
, arch
);
2260 /****************************************************************************
2261 ****************************************************************************/
2263 static WERROR
get_a_printer_driver_8(TALLOC_CTX
*mem_ctx
,
2264 struct spoolss_DriverInfo8
**driver
,
2265 const char *drivername
, const char *arch
,
2269 const char *architecture
;
2271 enum ndr_err_code ndr_err
;
2273 struct spoolss_DriverInfo8
*r
;
2277 architecture
= get_short_archi(arch
);
2278 if (!architecture
) {
2279 return WERR_UNKNOWN_PRINTER_DRIVER
;
2282 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2284 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
2288 DEBUG(8,("get_a_printer_driver_8: [%s%s/%d/%s]\n", DRIVERS_PREFIX8
,
2289 architecture
, version
, drivername
));
2291 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX8
,
2292 architecture
, version
, drivername
) < 0) {
2296 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
2299 return WERR_UNKNOWN_PRINTER_DRIVER
;
2302 r
= talloc(mem_ctx
, struct spoolss_DriverInfo8
);
2304 SAFE_FREE(dbuf
.dptr
);
2309 blob
= data_blob_const(dbuf
.dptr
, dbuf
.dsize
);
2311 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, NULL
, r
,
2312 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_DriverInfo8
);
2313 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2314 SAFE_FREE(dbuf
.dptr
);
2316 return WERR_UNKNOWN_PRINTER_DRIVER
;
2319 SAFE_FREE(dbuf
.dptr
);
2327 /****************************************************************************
2328 ****************************************************************************/
2329 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, uint8
*buf
, int buflen
)
2333 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2338 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2339 nt_devmode
->devicename
,
2340 nt_devmode
->formname
,
2342 nt_devmode
->specversion
,
2343 nt_devmode
->driverversion
,
2345 nt_devmode
->driverextra
,
2346 nt_devmode
->orientation
,
2347 nt_devmode
->papersize
,
2348 nt_devmode
->paperlength
,
2349 nt_devmode
->paperwidth
,
2352 nt_devmode
->defaultsource
,
2353 nt_devmode
->printquality
,
2356 nt_devmode
->yresolution
,
2357 nt_devmode
->ttoption
,
2358 nt_devmode
->collate
,
2359 nt_devmode
->logpixels
,
2362 nt_devmode
->bitsperpel
,
2363 nt_devmode
->pelswidth
,
2364 nt_devmode
->pelsheight
,
2365 nt_devmode
->displayflags
,
2366 nt_devmode
->displayfrequency
,
2367 nt_devmode
->icmmethod
,
2368 nt_devmode
->icmintent
,
2369 nt_devmode
->mediatype
,
2370 nt_devmode
->dithertype
,
2371 nt_devmode
->reserved1
,
2372 nt_devmode
->reserved2
,
2373 nt_devmode
->panningwidth
,
2374 nt_devmode
->panningheight
,
2375 nt_devmode
->nt_dev_private
);
2377 if (nt_devmode
->nt_dev_private
) {
2378 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2379 nt_devmode
->driverextra
,
2380 nt_devmode
->nt_dev_private
);
2383 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2388 /****************************************************************************
2389 Pack all values in all printer keys
2390 ***************************************************************************/
2392 static int pack_values(NT_PRINTER_DATA
*data
, uint8
*buf
, int buflen
)
2396 struct regval_blob
*val
;
2397 struct regval_ctr
*val_ctr
;
2404 /* loop over all keys */
2406 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2407 val_ctr
= data
->keys
[i
].values
;
2408 num_values
= regval_ctr_numvals( val_ctr
);
2410 /* pack the keyname followed by a empty value */
2412 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2413 &data
->keys
[i
].name
,
2419 /* now loop over all values */
2421 for ( j
=0; j
<num_values
; j
++ ) {
2422 /* pathname should be stored as <key>\<value> */
2424 val
= regval_ctr_specific_value( val_ctr
, j
);
2425 if (asprintf(&path
, "%s\\%s",
2427 regval_name(val
)) < 0) {
2431 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2436 regval_data_p(val
) );
2438 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2446 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2452 /****************************************************************************
2453 Delete a printer - this just deletes the printer info file, any open
2454 handles are not affected.
2455 ****************************************************************************/
2457 uint32
del_a_printer(const char *sharename
)
2460 char *printdb_path
= NULL
;
2461 TALLOC_CTX
*ctx
= talloc_tos();
2463 kbuf
= make_printer_tdbkey(ctx
, sharename
);
2464 tdb_delete(tdb_printers
, kbuf
);
2466 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
2467 tdb_delete(tdb_printers
, kbuf
);
2469 close_all_print_db();
2471 if (geteuid() == sec_initial_uid()) {
2472 if (asprintf(&printdb_path
, "%s%s.tdb",
2473 cache_path("printing/"),
2477 unlink(printdb_path
);
2478 SAFE_FREE(printdb_path
);
2484 /****************************************************************************
2485 ****************************************************************************/
2486 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2492 TDB_DATA kbuf
, dbuf
;
2495 * in addprinter: no servername and the printer is the name
2496 * in setprinter: servername is \\server
2497 * and printer is \\server\\printer
2499 * Samba manages only local printers.
2500 * we currently don't support things like i
2501 * path=\\other_server\printer
2503 * We only store the printername, not \\server\printername
2506 if ( info
->servername
[0] != '\0' ) {
2507 trim_string(info
->printername
, info
->servername
, NULL
);
2508 trim_char(info
->printername
, '\\', '\0');
2509 info
->servername
[0]='\0';
2513 * JFM: one day I'll forget.
2514 * below that's info->portname because that's the SAMBA sharename
2515 * and I made NT 'thinks' it's the portname
2516 * the info->sharename is the thing you can name when you add a printer
2517 * that's the short-name when you create shared printer for 95/98
2518 * So I've made a limitation in SAMBA: you can only have 1 printer model
2519 * behind a SAMBA share.
2527 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2530 info
->default_priority
,
2547 info
->printprocessor
,
2551 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2552 retlen
= pack_values( info
->data
, buf
+len
, buflen
-len
);
2559 if (buflen
!= len
) {
2560 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
2562 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2570 kbuf
= make_printer_tdbkey(talloc_tos(), info
->sharename
);
2575 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2578 if (!W_ERROR_IS_OK(ret
))
2579 DEBUG(8, ("error updating printer to tdb on disk\n"));
2583 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2584 info
->sharename
, info
->drivername
, info
->portname
, len
));
2590 /****************************************************************************
2591 Malloc and return an NT devicemode.
2592 ****************************************************************************/
2594 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2597 char adevice
[MAXDEVICENAME
];
2598 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2600 if (nt_devmode
== NULL
) {
2601 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2605 ZERO_STRUCTP(nt_devmode
);
2607 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2608 fstrcpy(nt_devmode
->devicename
, adevice
);
2610 fstrcpy(nt_devmode
->formname
, "Letter");
2612 nt_devmode
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2613 nt_devmode
->driverversion
= 0x0400;
2614 nt_devmode
->size
= 0x00DC;
2615 nt_devmode
->driverextra
= 0x0000;
2616 nt_devmode
->fields
= DEVMODE_FORMNAME
|
2618 DEVMODE_PRINTQUALITY
|
2619 DEVMODE_DEFAULTSOURCE
|
2623 DEVMODE_ORIENTATION
;
2624 nt_devmode
->orientation
= DMORIENT_PORTRAIT
;
2625 nt_devmode
->papersize
= DMPAPER_LETTER
;
2626 nt_devmode
->paperlength
= 0;
2627 nt_devmode
->paperwidth
= 0;
2628 nt_devmode
->scale
= 0x64;
2629 nt_devmode
->copies
= 1;
2630 nt_devmode
->defaultsource
= DMBIN_FORMSOURCE
;
2631 nt_devmode
->printquality
= DMRES_HIGH
; /* 0x0258 */
2632 nt_devmode
->color
= DMRES_MONOCHROME
;
2633 nt_devmode
->duplex
= DMDUP_SIMPLEX
;
2634 nt_devmode
->yresolution
= 0;
2635 nt_devmode
->ttoption
= DMTT_SUBDEV
;
2636 nt_devmode
->collate
= DMCOLLATE_FALSE
;
2637 nt_devmode
->icmmethod
= 0;
2638 nt_devmode
->icmintent
= 0;
2639 nt_devmode
->mediatype
= 0;
2640 nt_devmode
->dithertype
= 0;
2642 /* non utilisés par un driver d'imprimante */
2643 nt_devmode
->logpixels
= 0;
2644 nt_devmode
->bitsperpel
= 0;
2645 nt_devmode
->pelswidth
= 0;
2646 nt_devmode
->pelsheight
= 0;
2647 nt_devmode
->displayflags
= 0;
2648 nt_devmode
->displayfrequency
= 0;
2649 nt_devmode
->reserved1
= 0;
2650 nt_devmode
->reserved2
= 0;
2651 nt_devmode
->panningwidth
= 0;
2652 nt_devmode
->panningheight
= 0;
2654 nt_devmode
->nt_dev_private
= NULL
;
2658 /****************************************************************************
2659 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2660 ****************************************************************************/
2662 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2664 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2666 if(nt_devmode
== NULL
)
2669 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2671 SAFE_FREE(nt_devmode
->nt_dev_private
);
2672 SAFE_FREE(*devmode_ptr
);
2675 /****************************************************************************
2676 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2677 ****************************************************************************/
2679 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2681 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2686 free_nt_devicemode(&info
->devmode
);
2688 TALLOC_FREE( *info_ptr
);
2692 /****************************************************************************
2693 ****************************************************************************/
2694 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, const uint8
*buf
, int buflen
)
2698 NT_DEVICEMODE devmode
;
2700 ZERO_STRUCT(devmode
);
2702 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2704 if (!*nt_devmode
) return len
;
2706 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2710 &devmode
.specversion
,
2711 &devmode
.driverversion
,
2713 &devmode
.driverextra
,
2714 &devmode
.orientation
,
2716 &devmode
.paperlength
,
2717 &devmode
.paperwidth
,
2720 &devmode
.defaultsource
,
2721 &devmode
.printquality
,
2724 &devmode
.yresolution
,
2730 &devmode
.bitsperpel
,
2732 &devmode
.pelsheight
,
2733 &devmode
.displayflags
,
2734 &devmode
.displayfrequency
,
2738 &devmode
.dithertype
,
2741 &devmode
.panningwidth
,
2742 &devmode
.panningheight
,
2743 &devmode
.nt_dev_private
);
2745 if (devmode
.nt_dev_private
) {
2746 /* the len in tdb_unpack is an int value and
2747 * devmode.driverextra is only a short
2749 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2750 devmode
.driverextra
=(uint16
)extra_len
;
2752 /* check to catch an invalid TDB entry so we don't segfault */
2753 if (devmode
.driverextra
== 0) {
2754 devmode
.nt_dev_private
= NULL
;
2758 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2760 SAFE_FREE(devmode
.nt_dev_private
);
2764 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2765 if (devmode
.nt_dev_private
)
2766 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2771 /****************************************************************************
2772 Allocate and initialize a new slot.
2773 ***************************************************************************/
2775 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2780 if ( !name
|| !data
)
2783 /* allocate another slot in the NT_PRINTER_KEY array */
2785 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2786 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2792 key_index
= data
->num_keys
;
2794 /* initialze new key */
2796 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2798 if ( !(data
->keys
[key_index
].values
= TALLOC_ZERO_P( data
, struct regval_ctr
)) )
2803 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2808 /****************************************************************************
2809 search for a registry key name in the existing printer data
2810 ***************************************************************************/
2812 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2816 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2817 if ( strequal( data
->keys
[i
].name
, name
) ) {
2819 /* cleanup memory */
2821 TALLOC_FREE( data
->keys
[i
].name
);
2822 TALLOC_FREE( data
->keys
[i
].values
);
2824 /* if not the end of the array, move remaining elements down one slot */
2827 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2828 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2835 return data
->num_keys
;
2838 /****************************************************************************
2839 search for a registry key name in the existing printer data
2840 ***************************************************************************/
2842 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2847 if ( !data
|| !name
)
2850 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2852 /* loop over all existing keys */
2854 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2855 if ( strequal(data
->keys
[i
].name
, name
) ) {
2856 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2866 /****************************************************************************
2867 ***************************************************************************/
2869 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2873 int num_subkeys
= 0;
2875 fstring
*subkeys_ptr
= NULL
;
2886 /* special case of asking for the top level printer data registry key names */
2888 if ( strlen(key
) == 0 ) {
2889 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2891 /* found a match, so allocate space and copy the name */
2893 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2894 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2899 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
2906 /* asking for the subkeys of some key */
2907 /* subkey paths are stored in the key name using '\' as the delimiter */
2909 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2910 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
2912 /* if we found the exact key, then break */
2913 key_len
= strlen( key
);
2914 if ( strlen(data
->keys
[i
].name
) == key_len
)
2917 /* get subkey path */
2919 p
= data
->keys
[i
].name
+ key_len
;
2922 fstrcpy( subkeyname
, p
);
2923 if ( (p
= strchr( subkeyname
, '\\' )) )
2926 /* don't add a key more than once */
2928 for ( j
=0; j
<num_subkeys
; j
++ ) {
2929 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
2933 if ( j
!= num_subkeys
)
2936 /* found a match, so allocate space and copy the name */
2938 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
2939 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2944 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
2950 /* return error if the key was not found */
2952 if ( i
== data
->num_keys
) {
2953 SAFE_FREE(subkeys_ptr
);
2958 /* tag off the end */
2961 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
2963 *subkeys
= subkeys_ptr
;
2969 static void map_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2972 regval_ctr_delvalue(ctr
, val_name
);
2973 regval_ctr_addvalue_sz(ctr
, val_name
, sz
);
2976 static void map_dword_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2979 regval_ctr_delvalue(ctr
, val_name
);
2980 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
2981 (char *) &dword
, sizeof(dword
));
2984 static void map_bool_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2987 uint8 bin_bool
= (b
? 1 : 0);
2988 regval_ctr_delvalue(ctr
, val_name
);
2989 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
2990 (char *) &bin_bool
, sizeof(bin_bool
));
2993 static void map_single_multi_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
2994 const char *multi_sz
)
3001 regval_ctr_delvalue(ctr
, val_name
);
3002 regval_ctr_addvalue_multi_sz(ctr
, val_name
, a
);
3005 /****************************************************************************
3006 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3008 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3009 * @return bool indicating success or failure
3010 ***************************************************************************/
3012 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
3014 struct regval_ctr
*ctr
= NULL
;
3016 const char *dnssuffix
;
3017 char *allocated_string
= NULL
;
3018 const char *ascii_str
;
3021 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3022 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3023 ctr
= info2
->data
->keys
[i
].values
;
3025 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
3026 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
3028 /* we make the assumption that the netbios name is the same
3029 as the DNS name sinc ethe former will be what we used to
3032 dnssuffix
= get_mydnsdomname(talloc_tos());
3033 if (dnssuffix
&& *dnssuffix
) {
3034 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
3036 fstrcpy( longname
, global_myname() );
3039 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
3041 if (asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
) == -1) {
3044 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
3045 SAFE_FREE(allocated_string
);
3047 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
3048 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
3049 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
3050 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
3051 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
3052 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
3053 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
3054 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
3055 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
3057 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
3058 (info2
->attributes
&
3059 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
3061 switch (info2
->attributes
& 0x3) {
3063 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
3066 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
3069 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
3072 ascii_str
= "unknown";
3074 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
3079 /*****************************************************************
3080 ****************************************************************/
3082 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
3086 struct regval_ctr
*ctr
=NULL
;
3088 /* find the DsSpooler key */
3089 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3090 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3091 ctr
= info2
->data
->keys
[i
].values
;
3093 regval_ctr_delvalue(ctr
, "objectGUID");
3095 /* We used to store this as a REG_BINARY but that causes
3098 regval_ctr_addvalue_sz(ctr
, "objectGUID",
3099 GUID_string(talloc_tos(), &guid
));
3102 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
3103 NT_PRINTER_INFO_LEVEL
*printer
)
3107 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
, *srv_cn_escaped
, *sharename_escaped
;
3108 char *srv_dn_utf8
, **srv_cn_utf8
;
3111 const char *attrs
[] = {"objectGUID", NULL
};
3113 WERROR win_rc
= WERR_OK
;
3114 size_t converted_size
;
3116 /* build the ads mods */
3117 ctx
= talloc_init("nt_printer_publish_ads");
3122 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
3124 /* figure out where to publish */
3125 ads_find_machine_acct(ads
, &res
, global_myname());
3127 /* We use ldap_get_dn here as we need the answer
3128 * in utf8 to call ldap_explode_dn(). JRA. */
3130 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
3133 return WERR_SERVER_UNAVAILABLE
;
3135 ads_msgfree(ads
, res
);
3136 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3139 ldap_memfree(srv_dn_utf8
);
3140 return WERR_SERVER_UNAVAILABLE
;
3142 /* Now convert to CH_UNIX. */
3143 if (!pull_utf8_talloc(ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
)) {
3145 ldap_memfree(srv_dn_utf8
);
3146 ldap_memfree(srv_cn_utf8
);
3147 return WERR_SERVER_UNAVAILABLE
;
3149 if (!pull_utf8_talloc(ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
)) {
3151 ldap_memfree(srv_dn_utf8
);
3152 ldap_memfree(srv_cn_utf8
);
3153 TALLOC_FREE(srv_dn
);
3154 return WERR_SERVER_UNAVAILABLE
;
3157 ldap_memfree(srv_dn_utf8
);
3158 ldap_memfree(srv_cn_utf8
);
3160 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
3161 if (!srv_cn_escaped
) {
3163 return WERR_SERVER_UNAVAILABLE
;
3165 sharename_escaped
= escape_rdn_val_string_alloc(printer
->info_2
->sharename
);
3166 if (!sharename_escaped
) {
3167 SAFE_FREE(srv_cn_escaped
);
3169 return WERR_SERVER_UNAVAILABLE
;
3172 prt_dn
= talloc_asprintf(ctx
, "cn=%s-%s,%s", srv_cn_escaped
, sharename_escaped
, srv_dn
);
3174 SAFE_FREE(srv_cn_escaped
);
3175 SAFE_FREE(sharename_escaped
);
3177 mods
= ads_init_mods(ctx
);
3185 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3186 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3187 printer
->info_2
->sharename
);
3190 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3191 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
3193 for (i
=0; mods
[i
] != 0; i
++)
3195 mods
[i
] = (LDAPMod
*)-1;
3196 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3199 if (!ADS_ERR_OK(ads_rc
))
3200 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3202 /* retreive the guid and store it locally */
3203 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3205 ads_pull_guid(ads
, res
, &guid
);
3206 ads_msgfree(ads
, res
);
3207 store_printer_guid(printer
->info_2
, guid
);
3208 win_rc
= mod_a_printer(printer
, 2);
3215 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3216 NT_PRINTER_INFO_LEVEL
*printer
)
3219 LDAPMessage
*res
= NULL
;
3220 char *prt_dn
= NULL
;
3222 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3224 /* remove the printer from the directory */
3225 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3226 printer
->info_2
->sharename
, global_myname());
3228 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
3229 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
3231 ads_msgfree(ads
, res
);
3234 ads_rc
= ads_del_dn(ads
, prt_dn
);
3235 TALLOC_FREE(prt_dn
);
3239 ads_msgfree(ads
, res
);
3244 /****************************************************************************
3245 * Publish a printer in the directory
3247 * @param snum describing printer service
3248 * @return WERROR indicating status of publishing
3249 ***************************************************************************/
3251 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3254 ADS_STRUCT
*ads
= NULL
;
3255 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3258 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3259 if (!W_ERROR_IS_OK(win_rc
))
3263 case DSPRINT_PUBLISH
:
3264 case DSPRINT_UPDATE
:
3265 /* set the DsSpooler info and attributes */
3266 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3267 win_rc
= WERR_NOMEM
;
3271 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3273 case DSPRINT_UNPUBLISH
:
3274 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3277 win_rc
= WERR_NOT_SUPPORTED
;
3281 win_rc
= mod_a_printer(printer
, 2);
3282 if (!W_ERROR_IS_OK(win_rc
)) {
3283 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3287 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3289 DEBUG(3, ("ads_init() failed\n"));
3290 win_rc
= WERR_SERVER_UNAVAILABLE
;
3293 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3294 SAFE_FREE(ads
->auth
.password
);
3295 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3298 /* ads_connect() will find the DC for us */
3299 ads_rc
= ads_connect(ads
);
3300 if (!ADS_ERR_OK(ads_rc
)) {
3301 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3302 win_rc
= WERR_ACCESS_DENIED
;
3307 case DSPRINT_PUBLISH
:
3308 case DSPRINT_UPDATE
:
3309 win_rc
= nt_printer_publish_ads(ads
, printer
);
3311 case DSPRINT_UNPUBLISH
:
3312 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3317 free_a_printer(&printer
, 2);
3322 WERROR
check_published_printers(void)
3325 ADS_STRUCT
*ads
= NULL
;
3327 int n_services
= lp_numservices();
3328 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3330 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3332 DEBUG(3, ("ads_init() failed\n"));
3333 return WERR_SERVER_UNAVAILABLE
;
3335 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3336 SAFE_FREE(ads
->auth
.password
);
3337 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3340 /* ads_connect() will find the DC for us */
3341 ads_rc
= ads_connect(ads
);
3342 if (!ADS_ERR_OK(ads_rc
)) {
3343 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3345 ads_kdestroy("MEMORY:prtpub_cache");
3346 return WERR_ACCESS_DENIED
;
3349 for (snum
= 0; snum
< n_services
; snum
++) {
3350 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3353 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3354 lp_servicename(snum
))) &&
3355 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3356 nt_printer_publish_ads(ads
, printer
);
3358 free_a_printer(&printer
, 2);
3362 ads_kdestroy("MEMORY:prtpub_cache");
3366 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3369 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3370 struct regval_ctr
*ctr
;
3371 struct regval_blob
*guid_val
;
3377 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3379 if (!W_ERROR_IS_OK(win_rc
) ||
3380 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3381 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3382 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3383 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3385 free_a_printer(&printer
, 2);
3389 /* fetching printer guids really ought to be a separate function. */
3394 /* We used to store the guid as REG_BINARY, then swapped
3395 to REG_SZ for Vista compatibility so check for both */
3397 switch ( regval_type(guid_val
) ){
3399 blob
= data_blob_const(regval_data_p(guid_val
),
3400 regval_size(guid_val
));
3401 pull_reg_sz(talloc_tos(), &blob
, (const char **)&guid_str
);
3402 ret
= NT_STATUS_IS_OK(GUID_from_string( guid_str
, guid
));
3403 talloc_free(guid_str
);
3406 if ( regval_size(guid_val
) != sizeof(struct GUID
) ) {
3410 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct GUID
));
3413 DEBUG(0,("is_printer_published: GUID value stored as "
3414 "invaluid type (%d)\n", regval_type(guid_val
) ));
3419 free_a_printer(&printer
, 2);
3423 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3428 WERROR
check_published_printers(void)
3433 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3438 #endif /* HAVE_ADS */
3440 /****************************************************************************
3441 ***************************************************************************/
3443 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3445 NT_PRINTER_DATA
*data
;
3447 int removed_keys
= 0;
3451 empty_slot
= data
->num_keys
;
3454 return WERR_INVALID_PARAM
;
3456 /* remove all keys */
3458 if ( !strlen(key
) ) {
3460 TALLOC_FREE( data
);
3464 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3470 /* remove a specific key (and all subkeys) */
3472 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3473 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3474 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3475 data
->keys
[i
].name
));
3477 TALLOC_FREE( data
->keys
[i
].name
);
3478 TALLOC_FREE( data
->keys
[i
].values
);
3480 /* mark the slot as empty */
3482 ZERO_STRUCTP( &data
->keys
[i
] );
3486 /* find the first empty slot */
3488 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3489 if ( !data
->keys
[i
].name
) {
3496 if ( i
== data
->num_keys
)
3497 /* nothing was removed */
3498 return WERR_INVALID_PARAM
;
3500 /* move everything down */
3502 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3503 if ( data
->keys
[i
].name
) {
3504 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3505 ZERO_STRUCTP( &data
->keys
[i
] );
3513 data
->num_keys
-= removed_keys
;
3515 /* sanity check to see if anything is left */
3517 if ( !data
->num_keys
) {
3518 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3520 SAFE_FREE( data
->keys
);
3521 ZERO_STRUCTP( data
);
3527 /****************************************************************************
3528 ***************************************************************************/
3530 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3532 WERROR result
= WERR_OK
;
3535 /* we must have names on non-zero length */
3537 if ( !key
|| !*key
|| !value
|| !*value
)
3538 return WERR_INVALID_NAME
;
3540 /* find the printer key first */
3542 key_index
= lookup_printerkey( p2
->data
, key
);
3543 if ( key_index
== -1 )
3546 /* make sure the value exists so we can return the correct error code */
3548 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3549 return WERR_BADFILE
;
3551 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3553 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3559 /****************************************************************************
3560 ***************************************************************************/
3562 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3563 uint32 type
, uint8
*data
, int real_len
)
3565 WERROR result
= WERR_OK
;
3568 /* we must have names on non-zero length */
3570 if ( !key
|| !*key
|| !value
|| !*value
)
3571 return WERR_INVALID_NAME
;
3573 /* find the printer key first */
3575 key_index
= lookup_printerkey( p2
->data
, key
);
3576 if ( key_index
== -1 )
3577 key_index
= add_new_printer_key( p2
->data
, key
);
3579 if ( key_index
== -1 )
3582 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3583 type
, (const char *)data
, real_len
);
3585 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3586 key
, value
, type
, real_len
));
3591 /****************************************************************************
3592 ***************************************************************************/
3594 struct regval_blob
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3598 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3601 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3604 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3607 /****************************************************************************
3608 Unpack a list of registry values frem the TDB
3609 ***************************************************************************/
3611 static int unpack_values(NT_PRINTER_DATA
*printer_data
, const uint8
*buf
, int buflen
)
3616 const char *valuename
= NULL
;
3617 const char *keyname
= NULL
;
3621 struct regval_blob
*regval_p
;
3624 /* add the "PrinterDriverData" key first for performance reasons */
3626 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3628 /* loop and unpack the rest of the registry values */
3632 /* check to see if there are any more registry values */
3635 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3639 /* unpack the next regval */
3641 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3647 /* lookup for subkey names which have a type of REG_NONE */
3648 /* there's no data with this entry */
3650 if ( type
== REG_NONE
) {
3651 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3652 add_new_printer_key( printer_data
, string
);
3657 * break of the keyname from the value name.
3658 * Valuenames can have embedded '\'s so be careful.
3659 * only support one level of keys. See the
3660 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3664 str
= strchr_m( string
, '\\');
3666 /* Put in "PrinterDriverData" is no key specified */
3669 keyname
= SPOOL_PRINTERDATA_KEY
;
3678 /* see if we need a new key */
3680 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3681 key_index
= add_new_printer_key( printer_data
, keyname
);
3683 if ( key_index
== -1 ) {
3684 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3689 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3691 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3692 Thanks to Martin Zielinski for the hint. */
3694 if ( type
== REG_BINARY
&&
3695 strequal( keyname
, SPOOL_DSSPOOLER_KEY
) &&
3696 strequal( valuename
, "objectGUID" ) )
3700 /* convert the GUID to a UNICODE string */
3702 memcpy( &guid
, data_p
, sizeof(struct GUID
) );
3704 regval_ctr_addvalue_sz(printer_data
->keys
[key_index
].values
,
3706 GUID_string(talloc_tos(), &guid
));
3711 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
,
3712 valuename
, type
, (const char *)data_p
,
3716 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3723 /****************************************************************************
3724 ***************************************************************************/
3726 static char *last_from
;
3727 static char *last_to
;
3729 static const char *get_last_from(void)
3737 static const char *get_last_to(void)
3745 static bool set_last_from_to(const char *from
, const char *to
)
3747 char *orig_from
= last_from
;
3748 char *orig_to
= last_to
;
3750 last_from
= SMB_STRDUP(from
);
3751 last_to
= SMB_STRDUP(to
);
3753 SAFE_FREE(orig_from
);
3756 if (!last_from
|| !last_to
) {
3757 SAFE_FREE(last_from
);
3764 static void map_to_os2_driver(fstring drivername
)
3766 char *mapfile
= lp_os2_driver_map();
3767 char **lines
= NULL
;
3771 if (!strlen(drivername
))
3777 if (strequal(drivername
,get_last_from())) {
3778 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3779 drivername
,get_last_to()));
3780 fstrcpy(drivername
,get_last_to());
3784 lines
= file_lines_load(mapfile
, &numlines
,0,NULL
);
3785 if (numlines
== 0 || lines
== NULL
) {
3786 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3791 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3793 for( i
= 0; i
< numlines
; i
++) {
3794 char *nt_name
= lines
[i
];
3795 char *os2_name
= strchr(nt_name
,'=');
3802 while (isspace(*nt_name
))
3805 if (!*nt_name
|| strchr("#;",*nt_name
))
3809 int l
= strlen(nt_name
);
3810 while (l
&& isspace(nt_name
[l
-1])) {
3816 while (isspace(*os2_name
))
3820 int l
= strlen(os2_name
);
3821 while (l
&& isspace(os2_name
[l
-1])) {
3827 if (strequal(nt_name
,drivername
)) {
3828 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3829 set_last_from_to(drivername
,os2_name
);
3830 fstrcpy(drivername
,os2_name
);
3839 /****************************************************************************
3840 Get a default printer info 2 struct.
3841 ****************************************************************************/
3843 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
,
3844 const char *servername
,
3845 const char* sharename
,
3848 int snum
= lp_servicenumber(sharename
);
3850 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3851 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
3852 servername
, sharename
);
3853 fstrcpy(info
->sharename
, sharename
);
3854 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
3856 /* by setting the driver name to an empty string, a local NT admin
3857 can now run the **local** APW to install a local printer driver
3858 for a Samba shared printer in 2.2. Without this, drivers **must** be
3859 installed on the Samba server for NT clients --jerry */
3860 #if 0 /* JERRY --do not uncomment-- */
3861 if (!*info
->drivername
)
3862 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3866 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
3868 strlcpy(info
->comment
, "", sizeof(info
->comment
));
3869 fstrcpy(info
->printprocessor
, "winprint");
3870 fstrcpy(info
->datatype
, "RAW");
3873 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
3874 /* Pull the location and comment strings from cups if we don't
3876 if ( !strlen(info
->location
) || !strlen(info
->comment
) )
3877 cups_pull_comment_location( info
);
3881 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
3883 info
->starttime
= 0; /* Minutes since 12:00am GMT */
3884 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
3886 info
->default_priority
= 1;
3887 info
->setuptime
= (uint32
)time(NULL
);
3890 * I changed this as I think it is better to have a generic
3891 * DEVMODE than to crash Win2k explorer.exe --jerry
3892 * See the HP Deskjet 990c Win2k drivers for an example.
3894 * However the default devmode appears to cause problems
3895 * with the HP CLJ 8500 PCL driver. Hence the addition of
3896 * the "default devmode" parameter --jerry 22/01/2002
3899 if (lp_default_devmode(snum
)) {
3900 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
) {
3904 info
->devmode
= NULL
;
3907 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
3911 info
->data
= TALLOC_ZERO_P(info
, NT_PRINTER_DATA
);
3916 add_new_printer_key(info
->data
, SPOOL_PRINTERDATA_KEY
);
3922 free_nt_devicemode(&info
->devmode
);
3924 return WERR_ACCESS_DENIED
;
3927 /****************************************************************************
3928 ****************************************************************************/
3930 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
,
3931 const char *servername
,
3932 const char *sharename
,
3936 int snum
= lp_servicenumber(sharename
);
3937 TDB_DATA kbuf
, dbuf
;
3938 fstring printername
;
3939 char adevice
[MAXDEVICENAME
];
3940 char *comment
= NULL
;
3942 kbuf
= make_printer_tdbkey(talloc_tos(), sharename
);
3944 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
3946 return get_a_printer_2_default(info
, servername
,
3947 sharename
, get_loc_com
);
3950 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
3953 &info
->default_priority
,
3960 &info
->c_setprinter
,
3970 info
->printprocessor
,
3975 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
3979 /* Samba has to have shared raw drivers. */
3980 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
3981 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
3983 /* Restore the stripped strings. */
3984 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
3986 if ( lp_force_printername(snum
) ) {
3987 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
3989 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
3992 fstrcpy(info
->printername
, printername
);
3995 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
3996 /* Pull the location and comment strings from cups if we don't
3998 if ( !strlen(info
->location
) || !strlen(info
->comment
) )
3999 cups_pull_comment_location( info
);
4003 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4006 * Some client drivers freak out if there is a NULL devmode
4007 * (probably the driver is not checking before accessing
4008 * the devmode pointer) --jerry
4010 * See comments in get_a_printer_2_default()
4013 if (lp_default_devmode(snum
) && !info
->devmode
) {
4014 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4016 info
->devmode
= construct_nt_devicemode(printername
);
4019 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
4020 if (info
->devmode
) {
4021 fstrcpy(info
->devmode
->devicename
, adevice
);
4024 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
4025 DEBUG(0,("unpack_values: talloc() failed!\n"));
4026 SAFE_FREE(dbuf
.dptr
);
4029 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4031 /* This will get the current RPC talloc context, but we should be
4032 passing this as a parameter... fixme... JRA ! */
4034 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
4035 SAFE_FREE(dbuf
.dptr
);
4039 /* Fix for OS/2 drivers. */
4041 if (get_remote_arch() == RA_OS2
) {
4042 map_to_os2_driver(info
->drivername
);
4045 SAFE_FREE(dbuf
.dptr
);
4047 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4048 sharename
, info
->printername
, info
->drivername
));
4053 /****************************************************************************
4054 Debugging function, dump at level 6 the struct in the logs.
4055 ****************************************************************************/
4056 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4059 NT_PRINTER_INFO_LEVEL_2
*info2
;
4061 DEBUG(106,("Dumping printer at level [%d]\n", level
));
4066 if (printer
->info_2
== NULL
)
4070 info2
=printer
->info_2
;
4072 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
4073 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
4074 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
4075 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
4076 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
4077 DEBUGADD(106,("status:[%d]\n", info2
->status
));
4078 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
4079 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
4080 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
4081 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
4082 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
4084 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
4085 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
4086 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
4087 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
4088 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
4089 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
4090 DEBUGADD(106,("location:[%s]\n", info2
->location
));
4091 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
4092 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
4093 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
4094 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
4100 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
4108 /****************************************************************************
4109 Update the changeid time.
4110 This is SO NASTY as some drivers need this to change, others need it
4111 static. This value will change every second, and I must hope that this
4112 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4114 ****************************************************************************/
4116 static uint32
rev_changeid(void)
4120 get_process_uptime(&tv
);
4123 /* Return changeid as msec since spooler restart */
4124 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
4127 * This setting seems to work well but is too untested
4128 * to replace the above calculation. Left in for experiementation
4129 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4131 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
4137 * The function below are the high level ones.
4138 * only those ones must be called from the spoolss code.
4142 /****************************************************************************
4143 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4144 ****************************************************************************/
4146 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4150 dump_a_printer(printer
, level
);
4156 * Update the changestamp. Emperical tests show that the
4157 * ChangeID is always updated,but c_setprinter is
4158 * global spooler variable (not per printer).
4161 /* ChangeID **must** be increasing over the lifetime
4162 of client's spoolss service in order for the
4163 client's cache to show updates */
4165 printer
->info_2
->changeid
= rev_changeid();
4168 * Because one day someone will ask:
4169 * NT->NT An admin connection to a remote
4170 * printer show changes imeediately in
4171 * the properities dialog
4173 * A non-admin connection will only show the
4174 * changes after viewing the properites page
4175 * 2 times. Seems to be related to a
4176 * race condition in the client between the spooler
4177 * updating the local cache and the Explorer.exe GUI
4178 * actually displaying the properties.
4180 * This is fixed in Win2k. admin/non-admin
4181 * connections both display changes immediately.
4186 result
=update_a_printer_2(printer
->info_2
);
4190 result
=WERR_UNKNOWN_LEVEL
;
4197 /****************************************************************************
4198 Initialize printer devmode & data with previously saved driver init values.
4199 ****************************************************************************/
4201 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2
*info_ptr
)
4206 NT_PRINTER_INFO_LEVEL_2 info
;
4212 * Delete any printer data 'values' already set. When called for driver
4213 * replace, there will generally be some, but during an add printer, there
4214 * should not be any (if there are delete them).
4217 if ( info_ptr
->data
)
4218 delete_all_printer_data( info_ptr
, "" );
4220 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
,
4221 info_ptr
->drivername
) < 0) {
4225 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
4228 * When changing to a driver that has no init info in the tdb, remove
4229 * the previous drivers init info and leave the new on blank.
4231 free_nt_devicemode(&info_ptr
->devmode
);
4238 * Get the saved DEVMODE..
4241 len
+= unpack_devicemode(&info
.devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4244 * The saved DEVMODE contains the devicename from the printer used during
4245 * the initialization save. Change it to reflect the new printer.
4248 if ( info
.devmode
) {
4249 ZERO_STRUCT(info
.devmode
->devicename
);
4250 fstrcpy(info
.devmode
->devicename
, info_ptr
->printername
);
4254 * NT/2k does not change out the entire DeviceMode of a printer
4255 * when changing the driver. Only the driverextra, private, &
4256 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4258 * Later examination revealed that Windows NT/2k does reset the
4259 * the printer's device mode, bit **only** when you change a
4260 * property of the device mode such as the page orientation.
4265 /* Bind the saved DEVMODE to the new the printer */
4267 free_nt_devicemode(&info_ptr
->devmode
);
4268 info_ptr
->devmode
= info
.devmode
;
4270 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4271 info_ptr
->printername
, info_ptr
->devmode
?"VALID":"NULL", info_ptr
->drivername
));
4273 /* Add the printer data 'values' to the new printer */
4275 if ( !(info_ptr
->data
= TALLOC_ZERO_P( info_ptr
, NT_PRINTER_DATA
)) ) {
4276 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4280 len
+= unpack_values( info_ptr
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4282 SAFE_FREE(dbuf
.dptr
);
4287 /****************************************************************************
4288 Initialize printer devmode & data with previously saved driver init values.
4289 When a printer is created using AddPrinter, the drivername bound to the
4290 printer is used to lookup previously saved driver initialization info, which
4291 is bound to the new printer.
4292 ****************************************************************************/
4294 bool set_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4296 bool result
= False
;
4300 result
= set_driver_init_2(printer
->info_2
);
4304 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4312 /****************************************************************************
4313 Delete driver init data stored for a specified driver
4314 ****************************************************************************/
4316 bool del_driver_init(const char *drivername
)
4321 if (!drivername
|| !*drivername
) {
4322 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4326 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
, drivername
) < 0) {
4330 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4333 ret
= (tdb_delete_bystring(tdb_drivers
, key
) == 0);
4338 /****************************************************************************
4339 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4340 in the tdb. Note: this is different from the driver entry and the printer
4341 entry. There should be a single driver init entry for each driver regardless
4342 of whether it was installed from NT or 2K. Technically, they should be
4343 different, but they work out to the same struct.
4344 ****************************************************************************/
4346 static uint32
update_driver_init_2(NT_PRINTER_INFO_LEVEL_2
*info
)
4350 int buflen
, len
, ret
;
4359 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
4361 retlen
= pack_values( info
->data
, buf
+len
, buflen
-len
);
4369 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
4371 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4380 if (asprintf(&key
, "%s%s", DRIVER_INIT_PREFIX
, info
->drivername
) < 0) {
4388 ret
= tdb_store_bystring(tdb_drivers
, key
, dbuf
, TDB_REPLACE
);
4392 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4396 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4397 info
->sharename
, info
->drivername
));
4402 /****************************************************************************
4403 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4404 ****************************************************************************/
4406 static uint32
update_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4410 dump_a_printer(printer
, level
);
4414 result
= update_driver_init_2(printer
->info_2
);
4424 /****************************************************************************
4425 Convert the printer data value, a REG_BINARY array, into an initialization
4426 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4427 got to keep the endians happy :).
4428 ****************************************************************************/
4430 static bool convert_driver_init(TALLOC_CTX
*mem_ctx
, NT_DEVICEMODE
*nt_devmode
,
4431 const uint8_t *data
, uint32_t data_len
)
4433 struct spoolss_DeviceMode devmode
;
4434 enum ndr_err_code ndr_err
;
4437 ZERO_STRUCT(devmode
);
4439 blob
= data_blob_const(data
, data_len
);
4441 ndr_err
= ndr_pull_struct_blob(&blob
, mem_ctx
, NULL
, &devmode
,
4442 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_DeviceMode
);
4443 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
4444 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4448 return convert_devicemode("", &devmode
, &nt_devmode
);
4451 /****************************************************************************
4452 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4454 1. Use the driver's config DLL to this UNC printername and:
4455 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4456 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4457 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4459 The last step triggers saving the "driver initialization" information for
4460 this printer into the tdb. Later, new printers that use this driver will
4461 have this initialization information bound to them. This simulates the
4462 driver initialization, as if it had run on the Samba server (as it would
4465 The Win32 client side code requirement sucks! But until we can run arbitrary
4466 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4468 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4469 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4470 about it and you will realize why. JRR 010720
4471 ****************************************************************************/
4473 static WERROR
save_driver_init_2(NT_PRINTER_INFO_LEVEL
*printer
, uint8
*data
, uint32 data_len
)
4475 WERROR status
= WERR_OK
;
4476 TALLOC_CTX
*ctx
= NULL
;
4477 NT_DEVICEMODE
*nt_devmode
= NULL
;
4478 NT_DEVICEMODE
*tmp_devmode
= printer
->info_2
->devmode
;
4481 * When the DEVMODE is already set on the printer, don't try to unpack it.
4483 DEBUG(8,("save_driver_init_2: Enter...\n"));
4485 if ( !printer
->info_2
->devmode
&& data_len
) {
4487 * Set devmode on printer info, so entire printer initialization can be
4491 if ((ctx
= talloc_init("save_driver_init_2")) == NULL
)
4494 if ((nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
)) == NULL
) {
4495 status
= WERR_NOMEM
;
4499 ZERO_STRUCTP(nt_devmode
);
4502 * The DEVMODE is held in the 'data' component of the param in raw binary.
4503 * Convert it to to a devmode structure
4505 if ( !convert_driver_init( ctx
, nt_devmode
, data
, data_len
)) {
4506 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4507 status
= WERR_INVALID_PARAM
;
4511 printer
->info_2
->devmode
= nt_devmode
;
4515 * Pack up and add (or update) the DEVMODE and any current printer data to
4516 * a 'driver init' element in the tdb
4520 if ( update_driver_init(printer
, 2) != 0 ) {
4521 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4522 status
= WERR_NOMEM
;
4527 * If driver initialization info was successfully saved, set the current
4528 * printer to match it. This allows initialization of the current printer
4529 * as well as the driver.
4531 status
= mod_a_printer(printer
, 2);
4532 if (!W_ERROR_IS_OK(status
)) {
4533 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4534 printer
->info_2
->printername
));
4538 talloc_destroy(ctx
);
4539 free_nt_devicemode( &nt_devmode
);
4541 printer
->info_2
->devmode
= tmp_devmode
;
4546 /****************************************************************************
4547 Update the driver init info (DEVMODE and specifics) for a printer
4548 ****************************************************************************/
4550 WERROR
save_driver_init(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
, uint8
*data
, uint32 data_len
)
4552 WERROR status
= WERR_OK
;
4556 status
= save_driver_init_2( printer
, data
, data_len
);
4559 status
= WERR_UNKNOWN_LEVEL
;
4566 /****************************************************************************
4567 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4569 Previously the code had a memory allocation problem because it always
4570 used the TALLOC_CTX from the Printer_entry*. This context lasts
4571 as a long as the original handle is open. So if the client made a lot
4572 of getprinter[data]() calls, the memory usage would climb. Now we use
4573 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4574 still use the Printer_entry->ctx for maintaining the cache copy though
4575 since that object must live as long as the handle by definition.
4578 ****************************************************************************/
4580 static WERROR
get_a_printer_internal( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4581 const char *sharename
, bool get_loc_com
)
4586 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4588 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4589 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4595 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4596 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4597 TALLOC_FREE( *pp_printer
);
4602 fstrcpy( servername
, print_hnd
->servername
);
4604 fstrcpy( servername
, "%L" );
4605 standard_sub_basic( "", "", servername
,
4606 sizeof(servername
)-1 );
4609 result
= get_a_printer_2( (*pp_printer
)->info_2
,
4610 servername
, sharename
, get_loc_com
);
4612 /* we have a new printer now. Save it with this handle */
4614 if ( !W_ERROR_IS_OK(result
) ) {
4615 TALLOC_FREE( *pp_printer
);
4616 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4617 sharename
, (unsigned int)level
, win_errstr(result
)));
4621 dump_a_printer( *pp_printer
, level
);
4626 TALLOC_FREE( *pp_printer
);
4627 return WERR_UNKNOWN_LEVEL
;
4633 WERROR
get_a_printer( Printer_entry
*print_hnd
,
4634 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4636 const char *sharename
)
4638 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4642 WERROR
get_a_printer_search( Printer_entry
*print_hnd
,
4643 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4645 const char *sharename
)
4647 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4651 /****************************************************************************
4652 Deletes a NT_PRINTER_INFO_LEVEL struct.
4653 ****************************************************************************/
4655 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4657 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4664 if ( printer
->info_2
)
4665 free_nt_printer_info_level_2(&printer
->info_2
);
4669 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4673 TALLOC_FREE(*pp_printer
);
4678 /****************************************************************************
4679 ****************************************************************************/
4681 uint32_t add_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4682 struct spoolss_AddDriverInfoCtr
*r
,
4686 struct spoolss_DriverInfo8 info8
;
4690 DEBUG(10,("adding a printer at level [%d]\n", r
->level
));
4694 info8
.version
= r
->info
.info3
->version
;
4695 info8
.driver_name
= r
->info
.info3
->driver_name
;
4696 info8
.architecture
= r
->info
.info3
->architecture
;
4697 info8
.driver_path
= r
->info
.info3
->driver_path
;
4698 info8
.data_file
= r
->info
.info3
->data_file
;
4699 info8
.config_file
= r
->info
.info3
->config_file
;
4700 info8
.help_file
= r
->info
.info3
->help_file
;
4701 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
4702 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
4703 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
4704 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
4708 info8
.version
= r
->info
.info6
->version
;
4709 info8
.driver_name
= r
->info
.info6
->driver_name
;
4710 info8
.architecture
= r
->info
.info6
->architecture
;
4711 info8
.driver_path
= r
->info
.info6
->driver_path
;
4712 info8
.data_file
= r
->info
.info6
->data_file
;
4713 info8
.config_file
= r
->info
.info6
->config_file
;
4714 info8
.help_file
= r
->info
.info6
->help_file
;
4715 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
4716 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
4717 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
4718 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
4720 info8
.driver_date
= r
->info
.info6
->driver_date
;
4721 info8
.driver_version
= r
->info
.info6
->driver_version
;
4722 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
4723 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
4724 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
4725 info8
.provider
= r
->info
.info6
->provider
;
4728 info8
.version
= r
->info
.info8
->version
;
4729 info8
.driver_name
= r
->info
.info8
->driver_name
;
4730 info8
.architecture
= r
->info
.info8
->architecture
;
4731 info8
.driver_path
= r
->info
.info8
->driver_path
;
4732 info8
.data_file
= r
->info
.info8
->data_file
;
4733 info8
.config_file
= r
->info
.info8
->config_file
;
4734 info8
.help_file
= r
->info
.info8
->help_file
;
4735 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
4736 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
4737 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
4738 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
4740 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
4741 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
4743 info8
.driver_date
= r
->info
.info8
->driver_date
;
4744 info8
.driver_version
= r
->info
.info8
->driver_version
;
4745 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
4746 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
4747 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
4748 info8
.provider
= r
->info
.info8
->provider
;
4749 info8
.print_processor
= r
->info
.info8
->print_processor
;
4750 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
4751 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
4752 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
4754 info8
.inf_path
= r
->info
.info8
->inf_path
;
4755 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
4756 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
4757 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
4759 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
4760 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
4766 *driver_name
= talloc_strdup(mem_ctx
, info8
.driver_name
);
4767 if (!*driver_name
) {
4770 *version
= info8
.version
;
4772 return add_a_printer_driver_8(&info8
);
4775 /****************************************************************************
4776 ****************************************************************************/
4778 WERROR
get_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4779 struct spoolss_DriverInfo8
**driver
,
4780 const char *drivername
, const char *architecture
,
4784 struct spoolss_DriverInfo3 info3
;
4785 struct spoolss_DriverInfo8
*info8
;
4789 /* Sometime we just want any version of the driver */
4791 if (version
== DRIVER_ANY_VERSION
) {
4792 /* look for Win2k first and then for NT4 */
4793 result
= get_a_printer_driver_8(mem_ctx
,
4797 if (!W_ERROR_IS_OK(result
)) {
4798 result
= get_a_printer_driver_8(mem_ctx
,
4804 result
= get_a_printer_driver_8(mem_ctx
,
4811 if (W_ERROR_IS_OK(result
)) {
4815 /* falling back to lookup for old level 3 driver - gd */
4817 /* Sometime we just want any version of the driver */
4819 if (version
== DRIVER_ANY_VERSION
) {
4820 /* look for Win2k first and then for NT4 */
4821 result
= get_a_printer_driver_3(mem_ctx
,
4825 if (!W_ERROR_IS_OK(result
)) {
4826 result
= get_a_printer_driver_3(mem_ctx
,
4832 result
= get_a_printer_driver_3(mem_ctx
,
4839 if (!W_ERROR_IS_OK(result
)) {
4843 info8
= talloc_zero(mem_ctx
, struct spoolss_DriverInfo8
);
4848 info8
->version
= info3
.version
;
4849 info8
->driver_name
= info3
.driver_name
;
4850 info8
->architecture
= info3
.architecture
;
4851 info8
->driver_path
= info3
.driver_path
;
4852 info8
->data_file
= info3
.data_file
;
4853 info8
->config_file
= info3
.config_file
;
4854 info8
->help_file
= info3
.help_file
;
4855 info8
->dependent_files
= info3
.dependent_files
;
4856 info8
->monitor_name
= info3
.monitor_name
;
4857 info8
->default_datatype
= info3
.default_datatype
;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8
*driver
)
4869 talloc_free(driver
);
4874 /****************************************************************************
4875 Determine whether or not a particular driver is currently assigned
4877 ****************************************************************************/
4879 bool printer_driver_in_use(const struct spoolss_DriverInfo8
*r
)
4882 int n_services
= lp_numservices();
4883 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4884 bool in_use
= False
;
4890 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4892 /* loop through the printers.tdb and check for the drivername */
4894 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4895 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4898 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4901 if (strequal(r
->driver_name
, printer
->info_2
->drivername
))
4904 free_a_printer( &printer
, 2 );
4907 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4910 struct spoolss_DriverInfo8
*d
;
4913 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
4915 /* we can still remove the driver if there is one of
4916 "Windows NT x86" version 2 or 3 left */
4918 if (!strequal("Windows NT x86", r
->architecture
)) {
4919 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4922 switch (r
->version
) {
4924 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 3);
4927 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 2);
4930 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4932 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4937 /* now check the error code */
4939 if ( W_ERROR_IS_OK(werr
) ) {
4940 /* it's ok to remove the driver, we have other architctures left */
4942 free_a_printer_driver(d
);
4946 /* report that the driver is not in use by default */
4952 /**********************************************************************
4953 Check to see if a ogiven file is in use by *info
4954 *********************************************************************/
4956 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
4963 /* mz: skip files that are in the list but already deleted */
4964 if (!file
|| !file
[0]) {
4968 if (strequal(file
, info
->driver_path
))
4971 if (strequal(file
, info
->data_file
))
4974 if (strequal(file
, info
->config_file
))
4977 if (strequal(file
, info
->help_file
))
4980 /* see of there are any dependent files to examine */
4982 if (!info
->dependent_files
)
4985 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
4986 if (strequal(file
, info
->dependent_files
[i
]))
4995 /**********************************************************************
4996 Utility function to remove the dependent file pointed to by the
4997 input parameter from the list
4998 *********************************************************************/
5000 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
5003 /* bump everything down a slot */
5005 while (files
&& files
[idx
+1]) {
5006 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
5015 /**********************************************************************
5016 Check if any of the files used by src are also used by drv
5017 *********************************************************************/
5019 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
5020 struct spoolss_DriverInfo8
*src
,
5021 const struct spoolss_DriverInfo8
*drv
)
5023 bool in_use
= False
;
5029 /* check each file. Remove it from the src structure if it overlaps */
5031 if (drv_file_in_use(src
->driver_path
, drv
)) {
5033 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
5034 src
->driver_path
= talloc_strdup(mem_ctx
, "");
5035 if (!src
->driver_path
) { return false; }
5038 if (drv_file_in_use(src
->data_file
, drv
)) {
5040 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
5041 src
->data_file
= talloc_strdup(mem_ctx
, "");
5042 if (!src
->data_file
) { return false; }
5045 if (drv_file_in_use(src
->config_file
, drv
)) {
5047 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
5048 src
->config_file
= talloc_strdup(mem_ctx
, "");
5049 if (!src
->config_file
) { return false; }
5052 if (drv_file_in_use(src
->help_file
, drv
)) {
5054 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
5055 src
->help_file
= talloc_strdup(mem_ctx
, "");
5056 if (!src
->help_file
) { return false; }
5059 /* are there any dependentfiles to examine? */
5061 if (!src
->dependent_files
)
5064 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
5065 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
5067 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
5068 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
5076 /****************************************************************************
5077 Determine whether or not a particular driver files are currently being
5078 used by any other driver.
5080 Return value is True if any files were in use by other drivers
5081 and False otherwise.
5083 Upon return, *info has been modified to only contain the driver files
5084 which are not in use
5088 This needs to check all drivers to ensure that all files in use
5089 have been removed from *info, not just the ones in the first
5091 ****************************************************************************/
5093 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
5094 struct spoolss_DriverInfo8
*info
)
5099 fstring
*list
= NULL
;
5100 struct spoolss_DriverInfo8
*driver
;
5101 bool in_use
= false;
5106 version
= info
->version
;
5108 /* loop over all driver versions */
5110 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5112 /* get the list of drivers */
5115 ndrivers
= get_ntdrivers(&list
, info
->architecture
, version
);
5117 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5118 ndrivers
, info
->architecture
, version
));
5120 /* check each driver for overlap in files */
5122 for (i
=0; i
<ndrivers
; i
++) {
5123 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, list
[i
], info
->architecture
, version
))) {
5132 /* check if d2 uses any files from d1 */
5133 /* only if this is a different driver than the one being deleted */
5135 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
5136 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
5137 /* mz: Do not instantly return -
5138 * we need to ensure this file isn't
5139 * also in use by other drivers. */
5144 free_a_printer_driver(driver
);
5149 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5154 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
5157 struct smb_filename
*smb_fname
= NULL
;
5160 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
5162 if (!NT_STATUS_IS_OK(status
)) {
5166 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
5168 TALLOC_FREE(smb_fname
);
5172 /****************************************************************************
5173 Actually delete the driver files. Make sure that
5174 printer_driver_files_in_use() return False before calling
5176 ****************************************************************************/
5178 static bool delete_driver_files(struct pipes_struct
*rpc_pipe
,
5179 const struct spoolss_DriverInfo8
*r
)
5184 connection_struct
*conn
;
5187 fstring printdollar
;
5188 int printdollar_snum
;
5195 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5196 r
->driver_name
, r
->version
));
5198 fstrcpy(printdollar
, "print$");
5200 printdollar_snum
= find_service(printdollar
);
5201 if (printdollar_snum
== -1) {
5205 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
5206 lp_pathname(printdollar_snum
),
5207 rpc_pipe
->server_info
, &oldcwd
);
5208 if (!NT_STATUS_IS_OK(nt_status
)) {
5209 DEBUG(0,("delete_driver_files: create_conn_struct "
5210 "returned %s\n", nt_errstr(nt_status
)));
5214 if ( !CAN_WRITE(conn
) ) {
5215 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5219 /* now delete the files; must strip the '\print$' string from
5222 if (r
->driver_path
&& r
->driver_path
[0]) {
5223 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
5225 DEBUG(10,("deleting driverfile [%s]\n", s
));
5226 driver_unlink_internals(conn
, file
);
5230 if (r
->config_file
&& r
->config_file
[0]) {
5231 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
5233 DEBUG(10,("deleting configfile [%s]\n", s
));
5234 driver_unlink_internals(conn
, file
);
5238 if (r
->data_file
&& r
->data_file
[0]) {
5239 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
5241 DEBUG(10,("deleting datafile [%s]\n", s
));
5242 driver_unlink_internals(conn
, file
);
5246 if (r
->help_file
&& r
->help_file
[0]) {
5247 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
5249 DEBUG(10,("deleting helpfile [%s]\n", s
));
5250 driver_unlink_internals(conn
, file
);
5254 /* check if we are done removing files */
5256 if (r
->dependent_files
) {
5257 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
5260 /* bypass the "\print$" portion of the path */
5262 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
5264 DEBUG(10,("deleting dependent file [%s]\n", file
));
5265 driver_unlink_internals(conn
, file
);
5277 vfs_ChDir(conn
, oldcwd
);
5283 /****************************************************************************
5284 Remove a printer driver from the TDB. This assumes that the the driver was
5285 previously looked up.
5286 ***************************************************************************/
5288 WERROR
delete_printer_driver(struct pipes_struct
*rpc_pipe
,
5289 const struct spoolss_DriverInfo8
*r
,
5290 uint32 version
, bool delete_files
)
5297 /* delete the tdb data first */
5299 arch
= get_short_archi(r
->architecture
);
5301 return WERR_UNKNOWN_PRINTER_DRIVER
;
5304 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
5305 arch
, version
, r
->driver_name
) < 0) {
5308 if (asprintf(&key8
, "%s%s/%d/%s", DRIVERS_PREFIX8
,
5309 arch
, version
, r
->driver_name
) < 0) {
5314 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5315 key
, delete_files
? "TRUE" : "FALSE" ));
5317 /* check if the driver actually exists for this environment */
5319 dbuf
= tdb_fetch_bystring(tdb_drivers
, key8
);
5321 /* ok... the driver exists so the delete should return success */
5322 if (tdb_delete_bystring(tdb_drivers
, key8
) == -1) {
5323 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key8
));
5326 return WERR_ACCESS_DENIED
;
5328 SAFE_FREE(dbuf
.dptr
);
5329 goto driver_deleted
;
5332 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
5334 /* ok... the driver exists so the delete should return success */
5335 if (tdb_delete_bystring(tdb_drivers
, key
) == -1) {
5336 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
5339 return WERR_ACCESS_DENIED
;
5341 SAFE_FREE(dbuf
.dptr
);
5342 goto driver_deleted
;
5346 DEBUG(8,("delete_printer_driver: Driver unknown\n"));
5347 return WERR_UNKNOWN_PRINTER_DRIVER
;
5352 * now delete any associated files if delete_files == True
5353 * even if this part failes, we return succes because the
5354 * driver doesn not exist any more
5358 delete_driver_files(rpc_pipe
, r
);
5360 DEBUG(5,("delete_printer_driver: driver delete successful\n"));
5365 /****************************************************************************
5366 Store a security desc for a printer.
5367 ****************************************************************************/
5369 WERROR
nt_printing_setsec(const char *sharename
, SEC_DESC_BUF
*secdesc_ctr
)
5371 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5372 SEC_DESC_BUF
*old_secdesc_ctr
= NULL
;
5373 TALLOC_CTX
*mem_ctx
= NULL
;
5380 mem_ctx
= talloc_init("nt_printing_setsec");
5381 if (mem_ctx
== NULL
)
5384 /* The old owner and group sids of the security descriptor are not
5385 present when new ACEs are added or removed by changing printer
5386 permissions through NT. If they are NULL in the new security
5387 descriptor then copy them over from the old one. */
5389 if (!secdesc_ctr
->sd
->owner_sid
|| !secdesc_ctr
->sd
->group_sid
) {
5390 DOM_SID
*owner_sid
, *group_sid
;
5391 SEC_ACL
*dacl
, *sacl
;
5392 SEC_DESC
*psd
= NULL
;
5395 if (!nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
)) {
5396 status
= WERR_NOMEM
;
5400 /* Pick out correct owner and group sids */
5402 owner_sid
= secdesc_ctr
->sd
->owner_sid
?
5403 secdesc_ctr
->sd
->owner_sid
:
5404 old_secdesc_ctr
->sd
->owner_sid
;
5406 group_sid
= secdesc_ctr
->sd
->group_sid
?
5407 secdesc_ctr
->sd
->group_sid
:
5408 old_secdesc_ctr
->sd
->group_sid
;
5410 dacl
= secdesc_ctr
->sd
->dacl
?
5411 secdesc_ctr
->sd
->dacl
:
5412 old_secdesc_ctr
->sd
->dacl
;
5414 sacl
= secdesc_ctr
->sd
->sacl
?
5415 secdesc_ctr
->sd
->sacl
:
5416 old_secdesc_ctr
->sd
->sacl
;
5418 /* Make a deep copy of the security descriptor */
5420 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sd
->revision
, secdesc_ctr
->sd
->type
,
5421 owner_sid
, group_sid
,
5427 status
= WERR_NOMEM
;
5431 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
5434 if (!new_secdesc_ctr
) {
5435 new_secdesc_ctr
= secdesc_ctr
;
5438 /* Store the security descriptor in a tdb */
5440 nt_status
= marshall_sec_desc_buf(mem_ctx
, new_secdesc_ctr
,
5441 &blob
.data
, &blob
.length
);
5442 if (!NT_STATUS_IS_OK(nt_status
)) {
5443 status
= ntstatus_to_werror(nt_status
);
5447 kbuf
= make_printers_secdesc_tdbkey(mem_ctx
, sharename
);
5449 dbuf
.dptr
= (unsigned char *)blob
.data
;
5450 dbuf
.dsize
= blob
.length
;
5452 if (tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
)==0) {
5455 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
5456 status
= WERR_BADFUNC
;
5459 /* Free malloc'ed memory */
5460 talloc_free(blob
.data
);
5465 talloc_destroy(mem_ctx
);
5469 /****************************************************************************
5470 Construct a default security descriptor buffer for a printer.
5471 ****************************************************************************/
5473 static SEC_DESC_BUF
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5475 SEC_ACE ace
[5]; /* max number of ace entries */
5478 SEC_ACL
*psa
= NULL
;
5479 SEC_DESC_BUF
*sdb
= NULL
;
5480 SEC_DESC
*psd
= NULL
;
5484 /* Create an ACE where Everyone is allowed to print */
5486 sa
= PRINTER_ACE_PRINT
;
5487 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5488 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5490 /* Add the domain admins group if we are a DC */
5493 DOM_SID domadmins_sid
;
5495 sid_compose(&domadmins_sid
, get_global_sam_sid(),
5496 DOMAIN_GROUP_RID_ADMINS
);
5498 sa
= PRINTER_ACE_FULL_CONTROL
;
5499 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5500 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5501 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5502 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5503 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5505 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5506 sid_append_rid(&adm_sid
, DOMAIN_USER_RID_ADMIN
);
5508 sa
= PRINTER_ACE_FULL_CONTROL
;
5509 init_sec_ace(&ace
[i
++], &adm_sid
,
5510 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5511 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5512 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5513 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5516 /* add BUILTIN\Administrators as FULL CONTROL */
5518 sa
= PRINTER_ACE_FULL_CONTROL
;
5519 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5520 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5521 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5522 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5523 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5524 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5526 /* Make the security descriptor owned by the BUILTIN\Administrators */
5528 /* The ACL revision number in rpc_secdesc.h differs from the one
5529 created by NT when setting ACE entries in printer
5530 descriptors. NT4 complains about the property being edited by a
5533 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5534 psd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
,
5535 &global_sid_Builtin_Administrators
,
5536 &global_sid_Builtin_Administrators
,
5537 NULL
, psa
, &sd_size
);
5541 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5545 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5547 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5548 (unsigned int)sd_size
));
5553 /****************************************************************************
5554 Get a security desc for a printer.
5555 ****************************************************************************/
5557 bool nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, SEC_DESC_BUF
**secdesc_ctr
)
5565 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5566 sharename
= temp
+ 1;
5569 /* Fetch security descriptor from tdb */
5571 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
5573 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
5576 status
= unmarshall_sec_desc_buf(ctx
, dbuf
.dptr
, dbuf
.dsize
,
5578 SAFE_FREE(dbuf
.dptr
);
5580 if (NT_STATUS_IS_OK(status
)) {
5585 *secdesc_ctr
= construct_default_printer_sdb(ctx
);
5586 if (!*secdesc_ctr
) {
5590 status
= marshall_sec_desc_buf(ctx
, *secdesc_ctr
,
5591 &blob
.data
, &blob
.length
);
5592 if (NT_STATUS_IS_OK(status
)) {
5593 dbuf
.dptr
= (unsigned char *)blob
.data
;
5594 dbuf
.dsize
= blob
.length
;
5595 tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
);
5596 talloc_free(blob
.data
);
5599 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5600 this security descriptor has been created when winbindd was
5601 down. Take ownership of security descriptor. */
5603 if (sid_equal((*secdesc_ctr
)->sd
->owner_sid
, &global_sid_World
)) {
5606 /* Change sd owner to workgroup administrator */
5608 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5609 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
5610 SEC_DESC
*psd
= NULL
;
5615 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
5617 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sd
->revision
, (*secdesc_ctr
)->sd
->type
,
5619 (*secdesc_ctr
)->sd
->group_sid
,
5620 (*secdesc_ctr
)->sd
->sacl
,
5621 (*secdesc_ctr
)->sd
->dacl
,
5628 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5629 if (!new_secdesc_ctr
) {
5633 /* Swap with other one */
5635 *secdesc_ctr
= new_secdesc_ctr
;
5639 nt_printing_setsec(sharename
, *secdesc_ctr
);
5643 if (DEBUGLEVEL
>= 10) {
5644 SEC_ACL
*the_acl
= (*secdesc_ctr
)->sd
->dacl
;
5647 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5648 sharename
, the_acl
->num_aces
));
5650 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5651 DEBUG(10, ("%s %d %d 0x%08x\n",
5652 sid_string_dbg(&the_acl
->aces
[i
].trustee
),
5653 the_acl
->aces
[i
].type
, the_acl
->aces
[i
].flags
,
5654 the_acl
->aces
[i
].access_mask
));
5663 1: level not implemented
5664 2: file doesn't exist
5665 3: can't allocate memory
5666 4: can't free memory
5667 5: non existant struct
5671 A printer and a printer driver are 2 different things.
5672 NT manages them separatelly, Samba does the same.
5673 Why ? Simply because it's easier and it makes sense !
5675 Now explanation: You have 3 printers behind your samba server,
5676 2 of them are the same make and model (laser A and B). But laser B
5677 has an 3000 sheet feeder and laser A doesn't such an option.
5678 Your third printer is an old dot-matrix model for the accounting :-).
5680 If the /usr/local/samba/lib directory (default dir), you will have
5681 5 files to describe all of this.
5683 3 files for the printers (1 by printer):
5686 NTprinter_accounting
5687 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5688 NTdriver_printer model X
5689 NTdriver_printer model Y
5691 jfm: I should use this comment for the text file to explain
5692 same thing for the forms BTW.
5693 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5697 /* Convert generic access rights to printer object specific access rights.
5698 It turns out that NT4 security descriptors use generic access rights and
5699 NT5 the object specific ones. */
5701 void map_printer_permissions(SEC_DESC
*sd
)
5705 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5706 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5707 &printer_generic_mapping
);
5711 void map_job_permissions(SEC_DESC
*sd
)
5715 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5716 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5717 &job_generic_mapping
);
5722 /****************************************************************************
5723 Check a user has permissions to perform the given operation. We use the
5724 permission constants defined in include/rpc_spoolss.h to check the various
5725 actions we perform when checking printer access.
5727 PRINTER_ACCESS_ADMINISTER:
5728 print_queue_pause, print_queue_resume, update_printer_sec,
5729 update_printer, spoolss_addprinterex_level_2,
5730 _spoolss_setprinterdata
5735 JOB_ACCESS_ADMINISTER:
5736 print_job_delete, print_job_pause, print_job_resume,
5739 Try access control in the following order (for performance reasons):
5740 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5741 2) check security descriptor (bit comparisons in memory)
5742 3) "printer admins" (may result in numerous calls to winbind)
5744 ****************************************************************************/
5745 bool print_access_check(struct auth_serversupplied_info
*server_info
, int snum
,
5748 SEC_DESC_BUF
*secdesc
= NULL
;
5749 uint32 access_granted
;
5752 TALLOC_CTX
*mem_ctx
= NULL
;
5753 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5755 /* If user is NULL then use the current_user structure */
5757 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5759 if (server_info
->utok
.uid
== sec_initial_uid()
5760 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
5764 /* Get printer name */
5766 pname
= PRINTERNAME(snum
);
5768 if (!pname
|| !*pname
) {
5773 /* Get printer security descriptor */
5775 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5780 if (!nt_printing_getsec(mem_ctx
, pname
, &secdesc
)) {
5781 talloc_destroy(mem_ctx
);
5786 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5787 SEC_DESC_BUF
*parent_secdesc
= secdesc
;
5789 /* Create a child security descriptor to check permissions
5790 against. This is because print jobs are child objects
5791 objects of a printer. */
5793 status
= se_create_child_secdesc_buf(mem_ctx
, &secdesc
, parent_secdesc
->sd
, False
);
5795 if (!NT_STATUS_IS_OK(status
)) {
5796 talloc_destroy(mem_ctx
);
5797 errno
= map_errno_from_nt_status(status
);
5801 map_job_permissions(secdesc
->sd
);
5803 map_printer_permissions(secdesc
->sd
);
5807 status
= se_access_check(secdesc
->sd
, server_info
->ptok
, access_type
,
5810 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
5812 /* see if we need to try the printer admin list */
5814 if ((access_granted
== 0) &&
5815 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
5816 NULL
, NULL
, server_info
->ptok
,
5817 lp_printer_admin(snum
)))) {
5818 talloc_destroy(mem_ctx
);
5822 talloc_destroy(mem_ctx
);
5824 if (!NT_STATUS_IS_OK(status
)) {
5828 return NT_STATUS_IS_OK(status
);
5831 /****************************************************************************
5832 Check the time parameters allow a print operation.
5833 *****************************************************************************/
5835 bool print_time_access_check(const char *servicename
)
5837 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5839 time_t now
= time(NULL
);
5843 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
5846 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5850 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5852 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5855 free_a_printer(&printer
, 2);
5863 /****************************************************************************
5864 Fill in the servername sent in the _spoolss_open_printer_ex() call
5865 ****************************************************************************/
5867 char* get_server_name( Printer_entry
*printer
)
5869 return printer
->servername
;