2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
26 #include "registry/reg_objects.h"
28 static TDB_CONTEXT
*tdb_forms
; /* used for forms files */
29 static TDB_CONTEXT
*tdb_drivers
; /* used for driver files */
30 static TDB_CONTEXT
*tdb_printers
; /* used for printers files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
42 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
44 /* Map generic permissions to printer object specific permissions */
46 const struct generic_mapping printer_generic_mapping
= {
53 const struct standard_mapping printer_std_mapping
= {
60 /* Map generic permissions to print server object specific permissions */
62 const struct generic_mapping printserver_generic_mapping
= {
69 const struct generic_mapping printserver_std_mapping
= {
76 /* Map generic permissions to job object specific permissions */
78 const struct generic_mapping job_generic_mapping
= {
85 /* We need one default form to support our default printer. Msoft adds the
86 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
87 array index). Letter is always first, so (for the current code) additions
88 always put things in the correct order. */
89 static const nt_forms_struct default_forms
[] = {
90 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
92 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
93 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
94 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
95 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
96 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
97 {"A0",0x1,0xcd528,0x122488,0x0,0x0,0xcd528,0x122488},
98 {"A1",0x1,0x91050,0xcd528,0x0,0x0,0x91050,0xcd528},
99 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
100 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
101 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
102 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
103 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
104 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
105 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
106 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
107 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
108 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
109 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
110 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
111 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
112 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
113 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
114 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
115 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
116 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
117 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
118 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
119 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
120 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
121 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
122 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
123 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
124 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
125 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
126 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
127 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
128 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
129 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
130 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
131 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
132 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
133 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
134 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
135 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
136 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
137 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
138 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
139 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
140 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
141 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
142 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
143 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
144 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
145 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
146 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
147 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
148 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
149 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
150 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
151 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
152 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
153 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
154 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
155 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
156 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
157 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
158 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
159 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
160 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
161 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
162 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
163 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
164 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
165 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
166 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
167 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
168 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
169 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
170 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
171 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
172 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
173 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
174 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
175 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
176 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
177 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
178 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
179 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
180 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
181 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
182 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
183 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
184 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
185 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
186 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
187 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
188 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
189 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
190 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
191 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
192 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
193 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
194 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
195 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
196 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
197 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
198 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
199 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
200 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
201 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
202 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
203 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
204 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
205 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
206 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
207 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
208 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
209 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
212 static const struct print_architecture_table_node archi_table
[]= {
214 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
215 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
216 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
217 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
218 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
219 {"Windows IA64", SPL_ARCH_IA64
, 3 },
220 {"Windows x64", SPL_ARCH_X64
, 3 },
225 /****************************************************************************
226 generate a new TDB_DATA key for storing a printer
227 ****************************************************************************/
229 static TDB_DATA
make_printer_tdbkey(TALLOC_CTX
*ctx
, const char *sharename
)
235 fstrcpy(share
, sharename
);
238 keystr
= talloc_asprintf(ctx
, "%s%s", PRINTERS_PREFIX
, share
);
239 key
= string_term_tdb_data(keystr
? keystr
: "");
244 /****************************************************************************
245 generate a new TDB_DATA key for storing a printer security descriptor
246 ****************************************************************************/
248 static TDB_DATA
make_printers_secdesc_tdbkey(TALLOC_CTX
*ctx
,
249 const char* sharename
)
255 fstrcpy(share
, sharename
);
258 keystr
= talloc_asprintf(ctx
, "%s%s", SECDESC_PREFIX
, share
);
259 key
= string_term_tdb_data(keystr
? keystr
: "");
264 /****************************************************************************
265 ****************************************************************************/
267 static bool upgrade_to_version_3(void)
269 TDB_DATA kbuf
, newkey
, dbuf
;
271 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
273 for (kbuf
= tdb_firstkey(tdb_drivers
); kbuf
.dptr
;
274 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
276 dbuf
= tdb_fetch(tdb_drivers
, kbuf
);
278 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) == 0) {
279 DEBUG(0,("upgrade_to_version_3:moving form\n"));
280 if (tdb_store(tdb_forms
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
281 SAFE_FREE(dbuf
.dptr
);
282 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms
)));
285 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
286 SAFE_FREE(dbuf
.dptr
);
287 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
292 if (strncmp((const char *)kbuf
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
)) == 0) {
293 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
294 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
295 SAFE_FREE(dbuf
.dptr
);
296 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers
)));
299 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
300 SAFE_FREE(dbuf
.dptr
);
301 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
306 if (strncmp((const char *)kbuf
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
)) == 0) {
307 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
308 if (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) != 0) {
309 SAFE_FREE(dbuf
.dptr
);
310 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers
)));
313 if (tdb_delete(tdb_drivers
, kbuf
) != 0) {
314 SAFE_FREE(dbuf
.dptr
);
315 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers
)));
320 SAFE_FREE(dbuf
.dptr
);
326 /*******************************************************************
327 Fix an issue with security descriptors. Printer sec_desc must
328 use more than the generic bits that were previously used
329 in <= 3.0.14a. They must also have a owner and group SID assigned.
330 Otherwise, any printers than have been migrated to a Windows
331 host using printmig.exe will not be accessible.
332 *******************************************************************/
334 static int sec_desc_upg_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
335 TDB_DATA data
, void *state
)
338 struct sec_desc_buf
*sd_orig
= NULL
;
339 struct sec_desc_buf
*sd_new
, *sd_store
;
340 struct security_descriptor
*sec
, *new_sec
;
341 TALLOC_CTX
*ctx
= state
;
346 if (!data
.dptr
|| data
.dsize
== 0) {
350 if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) != 0 ) {
354 /* upgrade the security descriptor */
356 status
= unmarshall_sec_desc_buf(ctx
, data
.dptr
, data
.dsize
, &sd_orig
);
357 if (!NT_STATUS_IS_OK(status
)) {
358 /* delete bad entries */
359 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
360 (const char *)key
.dptr
));
361 tdb_delete( tdb_printers
, key
);
370 /* is this even valid? */
376 /* update access masks */
378 for ( i
=0; i
<sec
->dacl
->num_aces
; i
++ ) {
379 switch ( sec
->dacl
->aces
[i
].access_mask
) {
380 case (GENERIC_READ_ACCESS
| GENERIC_WRITE_ACCESS
| GENERIC_EXECUTE_ACCESS
):
381 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_PRINT
;
384 case GENERIC_ALL_ACCESS
:
385 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_FULL_CONTROL
;
388 case READ_CONTROL_ACCESS
:
389 sec
->dacl
->aces
[i
].access_mask
= PRINTER_ACE_MANAGE_DOCUMENTS
;
391 default: /* no change */
396 /* create a new struct security_descriptor with the appropriate owner and group SIDs */
398 new_sec
= make_sec_desc( ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
399 &global_sid_Builtin_Administrators
,
400 &global_sid_Builtin_Administrators
,
401 NULL
, NULL
, &size_new_sec
);
405 sd_new
= make_sec_desc_buf( ctx
, size_new_sec
, new_sec
);
410 if ( !(sd_store
= sec_desc_merge_buf( ctx
, sd_new
, sd_orig
)) ) {
411 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key
.dptr
));
417 sd_size
= ndr_size_security_descriptor(sd_store
->sd
, 0)
418 + sizeof(struct sec_desc_buf
);
420 status
= marshall_sec_desc_buf(ctx
, sd_store
, &data
.dptr
, &data
.dsize
);
421 if (!NT_STATUS_IS_OK(status
)) {
422 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key
.dptr
));
426 result
= tdb_store( tdb_printers
, key
, data
, TDB_REPLACE
);
428 /* 0 to continue and non-zero to stop traversal */
430 return (result
== -1);
433 /*******************************************************************
434 *******************************************************************/
436 static bool upgrade_to_version_4(void)
441 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
443 if ( !(ctx
= talloc_init( "upgrade_to_version_4" )) )
446 result
= tdb_traverse( tdb_printers
, sec_desc_upg_fn
, ctx
);
448 talloc_destroy( ctx
);
450 return ( result
!= -1 );
453 /*******************************************************************
454 Fix an issue with security descriptors. Printer sec_desc must
455 use more than the generic bits that were previously used
456 in <= 3.0.14a. They must also have a owner and group SID assigned.
457 Otherwise, any printers than have been migrated to a Windows
458 host using printmig.exe will not be accessible.
459 *******************************************************************/
461 static int normalize_printers_fn( TDB_CONTEXT
*the_tdb
, TDB_DATA key
,
462 TDB_DATA data
, void *state
)
464 TALLOC_CTX
*ctx
= talloc_tos();
467 if (!data
.dptr
|| data
.dsize
== 0)
470 /* upgrade printer records and security descriptors */
472 if ( strncmp((const char *) key
.dptr
, PRINTERS_PREFIX
, strlen(PRINTERS_PREFIX
) ) == 0 ) {
473 new_key
= make_printer_tdbkey(ctx
, (const char *)key
.dptr
+strlen(PRINTERS_PREFIX
) );
475 else if ( strncmp((const char *) key
.dptr
, SECDESC_PREFIX
, strlen(SECDESC_PREFIX
) ) == 0 ) {
476 new_key
= make_printers_secdesc_tdbkey(ctx
, (const char *)key
.dptr
+strlen(SECDESC_PREFIX
) );
479 /* ignore this record */
483 /* delete the original record and store under the normalized key */
485 if ( tdb_delete( the_tdb
, key
) != 0 ) {
486 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
491 if ( tdb_store( the_tdb
, new_key
, data
, TDB_REPLACE
) != 0 ) {
492 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
500 /*******************************************************************
501 *******************************************************************/
503 static bool upgrade_to_version_5(void)
508 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
510 if ( !(ctx
= talloc_init( "upgrade_to_version_5" )) )
513 result
= tdb_traverse( tdb_printers
, normalize_printers_fn
, NULL
);
515 talloc_destroy( ctx
);
517 return ( result
!= -1 );
520 /****************************************************************************
521 Open the NT printing tdbs. Done once before fork().
522 ****************************************************************************/
524 bool nt_printing_init(struct messaging_context
*msg_ctx
)
526 const char *vstring
= "INFO/version";
530 if ( tdb_drivers
&& tdb_printers
&& tdb_forms
)
534 tdb_close(tdb_drivers
);
535 tdb_drivers
= tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
537 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
538 state_path("ntdrivers.tdb"), strerror(errno
) ));
543 tdb_close(tdb_printers
);
544 tdb_printers
= tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
546 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
547 state_path("ntprinters.tdb"), strerror(errno
) ));
552 tdb_close(tdb_forms
);
553 tdb_forms
= tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT
, O_RDWR
|O_CREAT
, 0600);
555 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
556 state_path("ntforms.tdb"), strerror(errno
) ));
560 /* handle a Samba upgrade */
562 vers_id
= tdb_fetch_int32(tdb_drivers
, vstring
);
564 DEBUG(10, ("Fresh database\n"));
565 tdb_store_int32( tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
566 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
569 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
571 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_1
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_1
)) {
572 if (!upgrade_to_version_3())
574 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
575 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
578 if ((vers_id
== NTDRIVERS_DATABASE_VERSION_2
) || (IREV(vers_id
) == NTDRIVERS_DATABASE_VERSION_2
)) {
579 /* Written on a bigendian machine with old fetch_int code. Save as le. */
580 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
581 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_3
);
582 vers_id
= NTDRIVERS_DATABASE_VERSION_3
;
585 if (vers_id
== NTDRIVERS_DATABASE_VERSION_3
) {
586 if ( !upgrade_to_version_4() )
588 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_4
);
589 vers_id
= NTDRIVERS_DATABASE_VERSION_4
;
592 if (vers_id
== NTDRIVERS_DATABASE_VERSION_4
) {
593 if ( !upgrade_to_version_5() )
595 tdb_store_int32(tdb_drivers
, vstring
, NTDRIVERS_DATABASE_VERSION_5
);
596 vers_id
= NTDRIVERS_DATABASE_VERSION_5
;
600 if ( vers_id
!= NTDRIVERS_DATABASE_VERSION_5
) {
601 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id
));
606 update_c_setprinter(True
);
609 * register callback to handle updating printers as new
610 * drivers are installed
613 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_DRVUPGRADE
,
614 do_drv_upgrade_printer
);
616 /* of course, none of the message callbacks matter if you don't
617 tell messages.c that you interested in receiving PRINT_GENERAL
618 msgs. This is done in serverid_register() */
621 if ( lp_security() == SEC_ADS
) {
622 win_rc
= check_published_printers();
623 if (!W_ERROR_IS_OK(win_rc
))
624 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc
)));
630 /*******************************************************************
631 Function to allow filename parsing "the old way".
632 ********************************************************************/
634 static NTSTATUS
driver_unix_convert(connection_struct
*conn
,
635 const char *old_name
,
636 struct smb_filename
**smb_fname
)
639 TALLOC_CTX
*ctx
= talloc_tos();
640 char *name
= talloc_strdup(ctx
, old_name
);
643 return NT_STATUS_NO_MEMORY
;
646 name
= unix_clean_name(ctx
, name
);
648 return NT_STATUS_NO_MEMORY
;
650 trim_string(name
,"/","/");
652 status
= unix_convert(ctx
, conn
, name
, smb_fname
, 0);
653 if (!NT_STATUS_IS_OK(status
)) {
654 return NT_STATUS_NO_MEMORY
;
660 /*******************************************************************
661 tdb traversal function for counting printers.
662 ********************************************************************/
664 static int traverse_counting_printers(TDB_CONTEXT
*t
, TDB_DATA key
,
665 TDB_DATA data
, void *context
)
667 int *printer_count
= (int*)context
;
669 if (memcmp(PRINTERS_PREFIX
, key
.dptr
, sizeof(PRINTERS_PREFIX
)-1) == 0) {
671 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key
.dptr
, *printer_count
));
677 /*******************************************************************
678 Update the spooler global c_setprinter. This variable is initialized
679 when the parent smbd starts with the number of existing printers. It
680 is monotonically increased by the current number of printers *after*
681 each add or delete printer RPC. Only Microsoft knows why... JRR020119
682 ********************************************************************/
684 uint32
update_c_setprinter(bool initialize
)
687 int32 printer_count
= 0;
689 tdb_lock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
691 /* Traverse the tdb, counting the printers */
692 tdb_traverse(tdb_printers
, traverse_counting_printers
, (void *)&printer_count
);
694 /* If initializing, set c_setprinter to current printers count
695 * otherwise, bump it by the current printer count
698 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
) + printer_count
;
700 c_setprinter
= printer_count
;
702 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter
));
703 tdb_store_int32(tdb_printers
, GLOBAL_C_SETPRINTER
, c_setprinter
);
705 tdb_unlock_bystring(tdb_printers
, GLOBAL_C_SETPRINTER
);
707 return (uint32
)c_setprinter
;
710 /*******************************************************************
711 Get the spooler global c_setprinter, accounting for initialization.
712 ********************************************************************/
714 uint32
get_c_setprinter(void)
716 int32 c_setprinter
= tdb_fetch_int32(tdb_printers
, GLOBAL_C_SETPRINTER
);
718 if (c_setprinter
== (int32
)-1)
719 c_setprinter
= update_c_setprinter(True
);
721 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter
));
723 return (uint32
)c_setprinter
;
726 /****************************************************************************
727 Get builtin form struct list.
728 ****************************************************************************/
730 int get_builtin_ntforms(nt_forms_struct
**list
)
732 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
736 return ARRAY_SIZE(default_forms
);
739 /****************************************************************************
740 get a builtin form struct
741 ****************************************************************************/
743 bool get_a_builtin_ntform_by_string(const char *form_name
, nt_forms_struct
*form
)
746 DEBUGADD(6,("Looking for builtin form %s \n", form_name
));
747 for (i
=0; i
<ARRAY_SIZE(default_forms
); i
++) {
748 if (strequal(form_name
,default_forms
[i
].name
)) {
749 DEBUGADD(6,("Found builtin form %s \n", form_name
));
750 memcpy(form
,&default_forms
[i
],sizeof(*form
));
758 /****************************************************************************
759 get a form struct list.
760 ****************************************************************************/
762 int get_ntforms(nt_forms_struct
**list
)
764 TDB_DATA kbuf
, newkey
, dbuf
;
765 nt_forms_struct form
;
772 for (kbuf
= tdb_firstkey(tdb_forms
);
774 newkey
= tdb_nextkey(tdb_forms
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
)
776 if (strncmp((const char *)kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0)
779 dbuf
= tdb_fetch(tdb_forms
, kbuf
);
783 fstrcpy(form
.name
, (const char *)kbuf
.dptr
+strlen(FORMS_PREFIX
));
784 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
785 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
786 &form
.top
, &form
.right
, &form
.bottom
);
787 SAFE_FREE(dbuf
.dptr
);
788 if (ret
!= dbuf
.dsize
)
791 *list
= SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1);
793 DEBUG(0,("get_ntforms: Realloc fail.\n"));
804 /****************************************************************************
805 write a form struct list
806 ****************************************************************************/
808 int write_ntforms(nt_forms_struct
**list
, int number
)
810 TALLOC_CTX
*ctx
= talloc_tos();
817 for (i
=0;i
<number
;i
++) {
818 /* save index, so list is rebuilt in correct order */
819 len
= tdb_pack(NULL
, 0, "dddddddd",
820 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
821 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
826 buf
= TALLOC_ARRAY(ctx
, char, len
);
830 len
= tdb_pack((uint8
*)buf
, len
, "dddddddd",
831 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
832 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
834 key
= talloc_asprintf(ctx
, "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
839 dbuf
.dptr
= (uint8
*)buf
;
840 if (tdb_store_bystring(tdb_forms
, key
, dbuf
, TDB_REPLACE
) != 0) {
852 /****************************************************************************
853 add a form struct at the end of the list
854 ****************************************************************************/
855 bool add_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int *count
)
861 * NT tries to add forms even when
862 * they are already in the base
863 * only update the values if already present
868 for (n
=0; n
<*count
; n
++) {
869 if ( strequal((*list
)[n
].name
, form
->form_name
) ) {
876 if((*list
=SMB_REALLOC_ARRAY(*list
, nt_forms_struct
, n
+1)) == NULL
) {
877 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
880 fstrcpy((*list
)[n
].name
, form
->form_name
);
884 (*list
)[n
].flag
= form
->flags
;
885 (*list
)[n
].width
= form
->size
.width
;
886 (*list
)[n
].length
= form
->size
.height
;
887 (*list
)[n
].left
= form
->area
.left
;
888 (*list
)[n
].top
= form
->area
.top
;
889 (*list
)[n
].right
= form
->area
.right
;
890 (*list
)[n
].bottom
= form
->area
.bottom
;
892 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
893 update
? "updated" : "added", form
->form_name
));
898 /****************************************************************************
899 Delete a named form struct.
900 ****************************************************************************/
902 bool delete_a_form(nt_forms_struct
**list
, const char *del_name
, int *count
, WERROR
*ret
)
909 for (n
=0; n
<*count
; n
++) {
910 if (!strncmp((*list
)[n
].name
, del_name
, strlen(del_name
))) {
911 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name
));
917 DEBUG(10,("delete_a_form, [%s] not found\n", del_name
));
918 *ret
= WERR_INVALID_FORM_NAME
;
922 if (asprintf(&key
, "%s%s", FORMS_PREFIX
, (*list
)[n
].name
) < 0) {
926 if (tdb_delete_bystring(tdb_forms
, key
) != 0) {
935 /****************************************************************************
936 Update a form struct.
937 ****************************************************************************/
939 void update_a_form(nt_forms_struct
**list
, struct spoolss_AddFormInfo1
*form
, int count
)
943 DEBUG(106, ("[%s]\n", form
->form_name
));
944 for (n
=0; n
<count
; n
++) {
945 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
946 if (!strncmp((*list
)[n
].name
, form
->form_name
, strlen(form
->form_name
)))
950 if (n
==count
) return;
952 (*list
)[n
].flag
= form
->flags
;
953 (*list
)[n
].width
= form
->size
.width
;
954 (*list
)[n
].length
= form
->size
.height
;
955 (*list
)[n
].left
= form
->area
.left
;
956 (*list
)[n
].top
= form
->area
.top
;
957 (*list
)[n
].right
= form
->area
.right
;
958 (*list
)[n
].bottom
= form
->area
.bottom
;
961 /****************************************************************************
962 Get the nt drivers list.
963 Traverse the database and look-up the matching names.
964 ****************************************************************************/
965 int get_ntdrivers(fstring
**list
, const char *architecture
, uint32 version
)
968 const char *short_archi
;
970 TDB_DATA kbuf
, newkey
;
972 short_archi
= get_short_archi(architecture
);
977 if (asprintf(&key
, "%s%s/%d/", DRIVERS_PREFIX
,
978 short_archi
, version
) < 0) {
982 for (kbuf
= tdb_firstkey(tdb_drivers
);
984 newkey
= tdb_nextkey(tdb_drivers
, kbuf
), free(kbuf
.dptr
), kbuf
=newkey
) {
986 if (strncmp((const char *)kbuf
.dptr
, key
, strlen(key
)) != 0)
989 if((*list
= SMB_REALLOC_ARRAY(*list
, fstring
, total
+1)) == NULL
) {
990 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
995 fstrcpy((*list
)[total
], (const char *)kbuf
.dptr
+strlen(key
));
1003 /****************************************************************************
1004 Function to do the mapping between the long architecture name and
1006 ****************************************************************************/
1008 const char *get_short_archi(const char *long_archi
)
1012 DEBUG(107,("Getting architecture dependant directory\n"));
1015 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
1016 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
1018 if (archi_table
[i
].long_archi
==NULL
) {
1019 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi
));
1023 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1025 DEBUGADD(108,("index: [%d]\n", i
));
1026 DEBUGADD(108,("long architecture: [%s]\n", archi_table
[i
].long_archi
));
1027 DEBUGADD(108,("short architecture: [%s]\n", archi_table
[i
].short_archi
));
1029 return archi_table
[i
].short_archi
;
1032 /****************************************************************************
1033 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1034 There are two case to be covered here: PE (Portable Executable) and NE (New
1035 Executable) files. Both files support the same INFO structure, but PE files
1036 store the signature in unicode, and NE files store it as !unicode.
1037 returns -1 on error, 1 on version info found, and 0 on no version info found.
1038 ****************************************************************************/
1040 static int get_file_version(files_struct
*fsp
, char *fname
,uint32
*major
, uint32
*minor
)
1046 if ((buf
=(char *)SMB_MALLOC(DOS_HEADER_SIZE
)) == NULL
) {
1047 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1048 fname
, DOS_HEADER_SIZE
));
1052 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
1053 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1054 fname
, (unsigned long)byte_count
));
1055 goto no_version_info
;
1058 /* Is this really a DOS header? */
1059 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
1060 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1061 fname
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
1062 goto no_version_info
;
1065 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1066 if (SMB_VFS_LSEEK(fsp
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
1067 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1069 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1070 goto no_version_info
;
1073 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1074 if ((byte_count
= vfs_read_data(fsp
, buf
, NE_HEADER_SIZE
)) < NE_HEADER_SIZE
) {
1075 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1076 fname
, (unsigned long)byte_count
));
1077 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1078 goto no_version_info
;
1081 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1082 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
1083 unsigned int num_sections
;
1084 unsigned int section_table_bytes
;
1086 /* Just skip over optional header to get to section table */
1087 if (SMB_VFS_LSEEK(fsp
,
1088 SVAL(buf
,PE_HEADER_OPTIONAL_HEADER_SIZE
)-(NE_HEADER_SIZE
-PE_HEADER_SIZE
),
1089 SEEK_CUR
) == (SMB_OFF_T
)-1) {
1090 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1095 /* get the section table */
1096 num_sections
= SVAL(buf
,PE_HEADER_NUMBER_OF_SECTIONS
);
1097 section_table_bytes
= num_sections
* PE_HEADER_SECT_HEADER_SIZE
;
1098 if (section_table_bytes
== 0)
1102 if ((buf
=(char *)SMB_MALLOC(section_table_bytes
)) == NULL
) {
1103 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1104 fname
, section_table_bytes
));
1108 if ((byte_count
= vfs_read_data(fsp
, buf
, section_table_bytes
)) < section_table_bytes
) {
1109 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1110 fname
, (unsigned long)byte_count
));
1114 /* Iterate the section table looking for the resource section ".rsrc" */
1115 for (i
= 0; i
< num_sections
; i
++) {
1116 int sec_offset
= i
* PE_HEADER_SECT_HEADER_SIZE
;
1118 if (strcmp(".rsrc", &buf
[sec_offset
+PE_HEADER_SECT_NAME_OFFSET
]) == 0) {
1119 unsigned int section_pos
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_PTR_DATA_OFFSET
);
1120 unsigned int section_bytes
= IVAL(buf
,sec_offset
+PE_HEADER_SECT_SIZE_DATA_OFFSET
);
1122 if (section_bytes
== 0)
1126 if ((buf
=(char *)SMB_MALLOC(section_bytes
)) == NULL
) {
1127 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1128 fname
, section_bytes
));
1132 /* Seek to the start of the .rsrc section info */
1133 if (SMB_VFS_LSEEK(fsp
, section_pos
, SEEK_SET
) == (SMB_OFF_T
)-1) {
1134 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1139 if ((byte_count
= vfs_read_data(fsp
, buf
, section_bytes
)) < section_bytes
) {
1140 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1141 fname
, (unsigned long)byte_count
));
1145 if (section_bytes
< VS_VERSION_INFO_UNICODE_SIZE
)
1148 for (i
=0; i
<section_bytes
-VS_VERSION_INFO_UNICODE_SIZE
; i
++) {
1149 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1150 if (buf
[i
] == 'V' && buf
[i
+1] == '\0' && buf
[i
+2] == 'S') {
1151 /* Align to next long address */
1152 int pos
= (i
+ sizeof(VS_SIGNATURE
)*2 + 3) & 0xfffffffc;
1154 if (IVAL(buf
,pos
) == VS_MAGIC_VALUE
) {
1155 *major
= IVAL(buf
,pos
+VS_MAJOR_OFFSET
);
1156 *minor
= IVAL(buf
,pos
+VS_MINOR_OFFSET
);
1158 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1159 fname
, *major
, *minor
,
1160 (*major
>>16)&0xffff, *major
&0xffff,
1161 (*minor
>>16)&0xffff, *minor
&0xffff));
1170 /* Version info not found, fall back to origin date/time */
1171 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname
));
1175 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
1176 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) != NE_HEADER_TARGOS_WIN
) {
1177 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1178 fname
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
1179 /* At this point, we assume the file is in error. It still could be somthing
1180 * else besides a NE file, but it unlikely at this point. */
1184 /* Allocate a bit more space to speed up things */
1186 if ((buf
=(char *)SMB_MALLOC(VS_NE_BUF_SIZE
)) == NULL
) {
1187 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1188 fname
, PE_HEADER_SIZE
));
1192 /* This is a HACK! I got tired of trying to sort through the messy
1193 * 'NE' file format. If anyone wants to clean this up please have at
1194 * it, but this works. 'NE' files will eventually fade away. JRR */
1195 while((byte_count
= vfs_read_data(fsp
, buf
, VS_NE_BUF_SIZE
)) > 0) {
1196 /* Cover case that should not occur in a well formed 'NE' .dll file */
1197 if (byte_count
-VS_VERSION_INFO_SIZE
<= 0) break;
1199 for(i
=0; i
<byte_count
; i
++) {
1200 /* Fast skip past data that can't possibly match */
1201 if (buf
[i
] != 'V') continue;
1203 /* Potential match data crosses buf boundry, move it to beginning
1204 * of buf, and fill the buf with as much as it will hold. */
1205 if (i
>byte_count
-VS_VERSION_INFO_SIZE
) {
1208 memcpy(buf
, &buf
[i
], byte_count
-i
);
1209 if ((bc
= vfs_read_data(fsp
, &buf
[byte_count
-i
], VS_NE_BUF_SIZE
-
1210 (byte_count
-i
))) < 0) {
1212 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1217 byte_count
= bc
+ (byte_count
- i
);
1218 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
1223 /* Check that the full signature string and the magic number that
1224 * follows exist (not a perfect solution, but the chances that this
1225 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1226 * twice, as it is simpler to read the code. */
1227 if (strcmp(&buf
[i
], VS_SIGNATURE
) == 0) {
1228 /* Compute skip alignment to next long address */
1229 int skip
= -(SMB_VFS_LSEEK(fsp
, 0, SEEK_CUR
) - (byte_count
- i
) +
1230 sizeof(VS_SIGNATURE
)) & 3;
1231 if (IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
) != 0xfeef04bd) continue;
1233 *major
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MAJOR_OFFSET
);
1234 *minor
= IVAL(buf
,i
+sizeof(VS_SIGNATURE
)+skip
+VS_MINOR_OFFSET
);
1235 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1236 fname
, *major
, *minor
,
1237 (*major
>>16)&0xffff, *major
&0xffff,
1238 (*minor
>>16)&0xffff, *minor
&0xffff));
1245 /* Version info not found, fall back to origin date/time */
1246 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname
));
1251 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1252 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1253 fname
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
1264 /****************************************************************************
1265 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1266 share one or more files. During the MS installation process files are checked
1267 to insure that only a newer version of a shared file is installed over an
1268 older version. There are several possibilities for this comparison. If there
1269 is no previous version, the new one is newer (obviously). If either file is
1270 missing the version info structure, compare the creation date (on Unix use
1271 the modification date). Otherwise chose the numerically larger version number.
1272 ****************************************************************************/
1274 static int file_version_is_newer(connection_struct
*conn
, fstring new_file
, fstring old_file
)
1276 bool use_version
= true;
1280 time_t new_create_time
;
1284 time_t old_create_time
;
1286 struct smb_filename
*smb_fname
= NULL
;
1287 files_struct
*fsp
= NULL
;
1293 SET_STAT_INVALID(st
);
1294 new_create_time
= (time_t)0;
1295 old_create_time
= (time_t)0;
1297 /* Get file version info (if available) for previous file (if it exists) */
1298 status
= driver_unix_convert(conn
, old_file
, &smb_fname
);
1299 if (!NT_STATUS_IS_OK(status
)) {
1303 status
= SMB_VFS_CREATE_FILE(
1306 0, /* root_dir_fid */
1307 smb_fname
, /* fname */
1308 FILE_GENERIC_READ
, /* access_mask */
1309 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1310 FILE_OPEN
, /* create_disposition*/
1311 0, /* create_options */
1312 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1313 INTERNAL_OPEN_ONLY
, /* oplock_request */
1314 0, /* allocation_size */
1315 0, /* private_flags */
1321 if (!NT_STATUS_IS_OK(status
)) {
1322 /* Old file not found, so by definition new file is in fact newer */
1323 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1324 "errno = %d\n", smb_fname_str_dbg(smb_fname
),
1330 ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
1336 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1338 use_version
= false;
1339 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1342 old_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1343 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1344 (long)old_create_time
));
1347 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1350 /* Get file version info (if available) for new file */
1351 status
= driver_unix_convert(conn
, new_file
, &smb_fname
);
1352 if (!NT_STATUS_IS_OK(status
)) {
1356 status
= SMB_VFS_CREATE_FILE(
1359 0, /* root_dir_fid */
1360 smb_fname
, /* fname */
1361 FILE_GENERIC_READ
, /* access_mask */
1362 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1363 FILE_OPEN
, /* create_disposition*/
1364 0, /* create_options */
1365 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1366 INTERNAL_OPEN_ONLY
, /* oplock_request */
1367 0, /* allocation_size */
1368 0, /* private_flags */
1374 if (!NT_STATUS_IS_OK(status
)) {
1375 /* New file not found, this shouldn't occur if the caller did its job */
1376 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1377 "errno = %d\n", smb_fname_str_dbg(smb_fname
), errno
));
1381 ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1387 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1389 use_version
= false;
1390 if (SMB_VFS_FSTAT(fsp
, &st
) == -1) {
1393 new_create_time
= convert_timespec_to_time_t(st
.st_ex_mtime
);
1394 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1395 (long)new_create_time
));
1398 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1401 if (use_version
&& (new_major
!= old_major
|| new_minor
!= old_minor
)) {
1402 /* Compare versions and choose the larger version number */
1403 if (new_major
> old_major
||
1404 (new_major
== old_major
&& new_minor
> old_minor
)) {
1406 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1411 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1417 /* Compare modification time/dates and choose the newest time/date */
1418 if (new_create_time
> old_create_time
) {
1419 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file
, new_file
));
1424 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1432 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1435 TALLOC_FREE(smb_fname
);
1439 /****************************************************************************
1440 Determine the correct cVersion associated with an architecture and driver
1441 ****************************************************************************/
1442 static uint32
get_correct_cversion(struct pipes_struct
*p
,
1443 const char *architecture
,
1444 const char *driverpath_in
,
1449 struct smb_filename
*smb_fname
= NULL
;
1450 char *driverpath
= NULL
;
1451 files_struct
*fsp
= NULL
;
1452 connection_struct
*conn
= NULL
;
1455 fstring printdollar
;
1456 int printdollar_snum
;
1458 *perr
= WERR_INVALID_PARAM
;
1460 /* If architecture is Windows 95/98/ME, the version is always 0. */
1461 if (strcmp(architecture
, SPL_ARCH_WIN40
) == 0) {
1462 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1467 /* If architecture is Windows x64, the version is always 3. */
1468 if (strcmp(architecture
, SPL_ARCH_X64
) == 0) {
1469 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1474 fstrcpy(printdollar
, "print$");
1476 printdollar_snum
= find_service(printdollar
);
1477 if (printdollar_snum
== -1) {
1478 *perr
= WERR_NO_SUCH_SHARE
;
1482 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1483 lp_pathname(printdollar_snum
),
1484 p
->server_info
, &oldcwd
);
1485 if (!NT_STATUS_IS_OK(nt_status
)) {
1486 DEBUG(0,("get_correct_cversion: create_conn_struct "
1487 "returned %s\n", nt_errstr(nt_status
)));
1488 *perr
= ntstatus_to_werror(nt_status
);
1492 /* Open the driver file (Portable Executable format) and determine the
1493 * deriver the cversion. */
1494 driverpath
= talloc_asprintf(talloc_tos(),
1503 nt_status
= driver_unix_convert(conn
, driverpath
, &smb_fname
);
1504 if (!NT_STATUS_IS_OK(nt_status
)) {
1505 *perr
= ntstatus_to_werror(nt_status
);
1509 nt_status
= vfs_file_exist(conn
, smb_fname
);
1510 if (!NT_STATUS_IS_OK(nt_status
)) {
1511 *perr
= WERR_BADFILE
;
1515 status
= SMB_VFS_CREATE_FILE(
1518 0, /* root_dir_fid */
1519 smb_fname
, /* fname */
1520 FILE_GENERIC_READ
, /* access_mask */
1521 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
1522 FILE_OPEN
, /* create_disposition*/
1523 0, /* create_options */
1524 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
1525 INTERNAL_OPEN_ONLY
, /* oplock_request */
1526 0, /* private_flags */
1527 0, /* allocation_size */
1533 if (!NT_STATUS_IS_OK(status
)) {
1534 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1535 "%d\n", smb_fname_str_dbg(smb_fname
), errno
));
1536 *perr
= WERR_ACCESS_DENIED
;
1543 ret
= get_file_version(fsp
, smb_fname
->base_name
, &major
, &minor
);
1544 if (ret
== -1) goto error_exit
;
1547 DEBUG(6,("get_correct_cversion: Version info not "
1549 smb_fname_str_dbg(smb_fname
)));
1554 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1555 * for more details. Version in this case is not just the version of the
1556 * file, but the version in the sense of kernal mode (2) vs. user mode
1557 * (3) drivers. Other bits of the version fields are the version info.
1560 cversion
= major
& 0x0000ffff;
1562 case 2: /* WinNT drivers */
1563 case 3: /* Win2K drivers */
1567 DEBUG(6,("get_correct_cversion: cversion "
1568 "invalid [%s] cversion = %d\n",
1569 smb_fname_str_dbg(smb_fname
),
1574 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1575 " = 0x%x minor = 0x%x\n",
1576 smb_fname_str_dbg(smb_fname
), major
, minor
));
1579 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1580 smb_fname_str_dbg(smb_fname
), cversion
));
1587 TALLOC_FREE(smb_fname
);
1589 close_file(NULL
, fsp
, NORMAL_CLOSE
);
1592 vfs_ChDir(conn
, oldcwd
);
1595 if (cversion
!= -1) {
1601 /****************************************************************************
1602 ****************************************************************************/
1604 #define strip_driver_path(_mem_ctx, _element) do { \
1605 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1606 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1607 W_ERROR_HAVE_NO_MEMORY((_element)); \
1611 static WERROR
clean_up_driver_struct_level(TALLOC_CTX
*mem_ctx
,
1612 struct pipes_struct
*rpc_pipe
,
1613 const char *architecture
,
1614 const char **driver_path
,
1615 const char **data_file
,
1616 const char **config_file
,
1617 const char **help_file
,
1618 struct spoolss_StringArray
*dependent_files
,
1621 const char *short_architecture
;
1626 if (!*driver_path
|| !*data_file
|| !*config_file
) {
1627 return WERR_INVALID_PARAM
;
1630 /* clean up the driver name.
1631 * we can get .\driver.dll
1632 * or worse c:\windows\system\driver.dll !
1634 /* using an intermediate string to not have overlaping memcpy()'s */
1636 strip_driver_path(mem_ctx
, *driver_path
);
1637 strip_driver_path(mem_ctx
, *data_file
);
1638 strip_driver_path(mem_ctx
, *config_file
);
1640 strip_driver_path(mem_ctx
, *help_file
);
1643 if (dependent_files
&& dependent_files
->string
) {
1644 for (i
=0; dependent_files
->string
[i
]; i
++) {
1645 strip_driver_path(mem_ctx
, dependent_files
->string
[i
]);
1649 short_architecture
= get_short_archi(architecture
);
1650 if (!short_architecture
) {
1651 return WERR_UNKNOWN_PRINTER_DRIVER
;
1654 /* jfm:7/16/2000 the client always sends the cversion=0.
1655 * The server should check which version the driver is by reading
1656 * the PE header of driver->driverpath.
1658 * For Windows 95/98 the version is 0 (so the value sent is correct)
1659 * For Windows NT (the architecture doesn't matter)
1660 * NT 3.1: cversion=0
1661 * NT 3.5/3.51: cversion=1
1666 *version
= get_correct_cversion(rpc_pipe
, short_architecture
,
1667 *driver_path
, &err
);
1668 if (*version
== -1) {
1675 /****************************************************************************
1676 ****************************************************************************/
1678 WERROR
clean_up_driver_struct(struct pipes_struct
*rpc_pipe
,
1679 struct spoolss_AddDriverInfoCtr
*r
)
1683 return clean_up_driver_struct_level(r
, rpc_pipe
,
1684 r
->info
.info3
->architecture
,
1685 &r
->info
.info3
->driver_path
,
1686 &r
->info
.info3
->data_file
,
1687 &r
->info
.info3
->config_file
,
1688 &r
->info
.info3
->help_file
,
1689 r
->info
.info3
->dependent_files
,
1690 &r
->info
.info3
->version
);
1692 return clean_up_driver_struct_level(r
, rpc_pipe
,
1693 r
->info
.info6
->architecture
,
1694 &r
->info
.info6
->driver_path
,
1695 &r
->info
.info6
->data_file
,
1696 &r
->info
.info6
->config_file
,
1697 &r
->info
.info6
->help_file
,
1698 r
->info
.info6
->dependent_files
,
1699 &r
->info
.info6
->version
);
1701 return WERR_NOT_SUPPORTED
;
1705 /****************************************************************************
1706 This function sucks and should be replaced. JRA.
1707 ****************************************************************************/
1709 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3
*dst
,
1710 const struct spoolss_AddDriverInfo6
*src
)
1712 dst
->version
= src
->version
;
1714 dst
->driver_name
= src
->driver_name
;
1715 dst
->architecture
= src
->architecture
;
1716 dst
->driver_path
= src
->driver_path
;
1717 dst
->data_file
= src
->data_file
;
1718 dst
->config_file
= src
->config_file
;
1719 dst
->help_file
= src
->help_file
;
1720 dst
->monitor_name
= src
->monitor_name
;
1721 dst
->default_datatype
= src
->default_datatype
;
1722 dst
->_ndr_size_dependent_files
= src
->_ndr_size_dependent_files
;
1723 dst
->dependent_files
= src
->dependent_files
;
1726 /****************************************************************************
1727 This function sucks and should be replaced. JRA.
1728 ****************************************************************************/
1730 static void convert_level_8_to_level3(TALLOC_CTX
*mem_ctx
,
1731 struct spoolss_AddDriverInfo3
*dst
,
1732 const struct spoolss_DriverInfo8
*src
)
1734 dst
->version
= src
->version
;
1735 dst
->driver_name
= src
->driver_name
;
1736 dst
->architecture
= src
->architecture
;
1737 dst
->driver_path
= src
->driver_path
;
1738 dst
->data_file
= src
->data_file
;
1739 dst
->config_file
= src
->config_file
;
1740 dst
->help_file
= src
->help_file
;
1741 dst
->monitor_name
= src
->monitor_name
;
1742 dst
->default_datatype
= src
->default_datatype
;
1743 if (src
->dependent_files
) {
1744 dst
->dependent_files
= talloc_zero(mem_ctx
, struct spoolss_StringArray
);
1745 if (!dst
->dependent_files
) return;
1746 dst
->dependent_files
->string
= src
->dependent_files
;
1748 dst
->dependent_files
= NULL
;
1752 /****************************************************************************
1753 ****************************************************************************/
1755 static WERROR
move_driver_file_to_download_area(TALLOC_CTX
*mem_ctx
,
1756 connection_struct
*conn
,
1757 const char *driver_file
,
1758 const char *short_architecture
,
1759 uint32_t driver_version
,
1762 struct smb_filename
*smb_fname_old
= NULL
;
1763 struct smb_filename
*smb_fname_new
= NULL
;
1764 char *old_name
= NULL
;
1765 char *new_name
= NULL
;
1769 old_name
= talloc_asprintf(mem_ctx
, "%s/%s",
1770 short_architecture
, driver_file
);
1771 W_ERROR_HAVE_NO_MEMORY(old_name
);
1773 new_name
= talloc_asprintf(mem_ctx
, "%s/%d/%s",
1774 short_architecture
, driver_version
, driver_file
);
1775 if (new_name
== NULL
) {
1776 TALLOC_FREE(old_name
);
1780 if (version
!= -1 && (version
= file_version_is_newer(conn
, old_name
, new_name
)) > 0) {
1782 status
= driver_unix_convert(conn
, old_name
, &smb_fname_old
);
1783 if (!NT_STATUS_IS_OK(status
)) {
1788 /* Setup a synthetic smb_filename struct */
1789 smb_fname_new
= TALLOC_ZERO_P(mem_ctx
, struct smb_filename
);
1790 if (!smb_fname_new
) {
1795 smb_fname_new
->base_name
= new_name
;
1797 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1798 "'%s'\n", smb_fname_old
->base_name
,
1799 smb_fname_new
->base_name
));
1801 status
= copy_file(mem_ctx
, conn
, smb_fname_old
, smb_fname_new
,
1802 OPENX_FILE_EXISTS_TRUNCATE
|
1803 OPENX_FILE_CREATE_IF_NOT_EXIST
,
1806 if (!NT_STATUS_IS_OK(status
)) {
1807 DEBUG(0,("move_driver_file_to_download_area: Unable "
1808 "to rename [%s] to [%s]: %s\n",
1809 smb_fname_old
->base_name
, new_name
,
1810 nt_errstr(status
)));
1811 ret
= WERR_ACCESS_DENIED
;
1818 TALLOC_FREE(smb_fname_old
);
1819 TALLOC_FREE(smb_fname_new
);
1823 WERROR
move_driver_to_download_area(struct pipes_struct
*p
,
1824 struct spoolss_AddDriverInfoCtr
*r
,
1827 struct spoolss_AddDriverInfo3
*driver
;
1828 struct spoolss_AddDriverInfo3 converted_driver
;
1829 const char *short_architecture
;
1830 struct smb_filename
*smb_dname
= NULL
;
1831 char *new_dir
= NULL
;
1832 connection_struct
*conn
= NULL
;
1835 TALLOC_CTX
*ctx
= talloc_tos();
1838 fstring printdollar
;
1839 int printdollar_snum
;
1845 driver
= r
->info
.info3
;
1848 convert_level_6_to_level3(&converted_driver
, r
->info
.info6
);
1849 driver
= &converted_driver
;
1852 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r
->level
));
1853 return WERR_UNKNOWN_LEVEL
;
1856 short_architecture
= get_short_archi(driver
->architecture
);
1857 if (!short_architecture
) {
1858 return WERR_UNKNOWN_PRINTER_DRIVER
;
1861 fstrcpy(printdollar
, "print$");
1863 printdollar_snum
= find_service(printdollar
);
1864 if (printdollar_snum
== -1) {
1865 *perr
= WERR_NO_SUCH_SHARE
;
1866 return WERR_NO_SUCH_SHARE
;
1869 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
1870 lp_pathname(printdollar_snum
),
1871 p
->server_info
, &oldcwd
);
1872 if (!NT_STATUS_IS_OK(nt_status
)) {
1873 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1874 "returned %s\n", nt_errstr(nt_status
)));
1875 *perr
= ntstatus_to_werror(nt_status
);
1879 new_dir
= talloc_asprintf(ctx
,
1887 nt_status
= driver_unix_convert(conn
, new_dir
, &smb_dname
);
1888 if (!NT_STATUS_IS_OK(nt_status
)) {
1893 DEBUG(5,("Creating first directory: %s\n", smb_dname
->base_name
));
1895 create_directory(conn
, NULL
, smb_dname
);
1897 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1898 * listed for this driver which has already been moved, skip it (note:
1899 * drivers may list the same file name several times. Then check if the
1900 * file already exists in archi\version\, if so, check that the version
1901 * info (or time stamps if version info is unavailable) is newer (or the
1902 * date is later). If it is, move it to archi\version\filexxx.yyy.
1903 * Otherwise, delete the file.
1905 * If a file is not moved to archi\version\ because of an error, all the
1906 * rest of the 'unmoved' driver files are removed from archi\. If one or
1907 * more of the driver's files was already moved to archi\version\, it
1908 * potentially leaves the driver in a partially updated state. Version
1909 * trauma will most likely occur if an client attempts to use any printer
1910 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1911 * done is appropriate... later JRR
1914 DEBUG(5,("Moving files now !\n"));
1916 if (driver
->driver_path
&& strlen(driver
->driver_path
)) {
1918 *perr
= move_driver_file_to_download_area(ctx
,
1920 driver
->driver_path
,
1924 if (!W_ERROR_IS_OK(*perr
)) {
1925 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1932 if (driver
->data_file
&& strlen(driver
->data_file
)) {
1933 if (!strequal(driver
->data_file
, driver
->driver_path
)) {
1935 *perr
= move_driver_file_to_download_area(ctx
,
1941 if (!W_ERROR_IS_OK(*perr
)) {
1942 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1950 if (driver
->config_file
&& strlen(driver
->config_file
)) {
1951 if (!strequal(driver
->config_file
, driver
->driver_path
) &&
1952 !strequal(driver
->config_file
, driver
->data_file
)) {
1954 *perr
= move_driver_file_to_download_area(ctx
,
1956 driver
->config_file
,
1960 if (!W_ERROR_IS_OK(*perr
)) {
1961 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1969 if (driver
->help_file
&& strlen(driver
->help_file
)) {
1970 if (!strequal(driver
->help_file
, driver
->driver_path
) &&
1971 !strequal(driver
->help_file
, driver
->data_file
) &&
1972 !strequal(driver
->help_file
, driver
->config_file
)) {
1974 *perr
= move_driver_file_to_download_area(ctx
,
1980 if (!W_ERROR_IS_OK(*perr
)) {
1981 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
1989 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
1990 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
1991 if (!strequal(driver
->dependent_files
->string
[i
], driver
->driver_path
) &&
1992 !strequal(driver
->dependent_files
->string
[i
], driver
->data_file
) &&
1993 !strequal(driver
->dependent_files
->string
[i
], driver
->config_file
) &&
1994 !strequal(driver
->dependent_files
->string
[i
], driver
->help_file
)) {
1996 for (j
=0; j
< i
; j
++) {
1997 if (strequal(driver
->dependent_files
->string
[i
], driver
->dependent_files
->string
[j
])) {
2002 *perr
= move_driver_file_to_download_area(ctx
,
2004 driver
->dependent_files
->string
[i
],
2008 if (!W_ERROR_IS_OK(*perr
)) {
2009 if (W_ERROR_EQUAL(*perr
, WERR_ACCESS_DENIED
)) {
2020 TALLOC_FREE(smb_dname
);
2023 vfs_ChDir(conn
, oldcwd
);
2027 if (W_ERROR_EQUAL(*perr
, WERR_OK
)) {
2031 return WERR_UNKNOWN_PRINTER_DRIVER
;
2036 /****************************************************************************
2037 ****************************************************************************/
2039 static uint32
add_a_printer_driver_3(struct spoolss_AddDriverInfo3
*driver
)
2041 TALLOC_CTX
*ctx
= talloc_tos();
2043 const char *architecture
;
2044 char *directory
= NULL
;
2050 architecture
= get_short_archi(driver
->architecture
);
2051 if (!architecture
) {
2055 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2056 * \\server is added in the rpc server layer.
2057 * It does make sense to NOT store the server's name in the printer TDB.
2060 directory
= talloc_asprintf(ctx
, "\\print$\\%s\\%d\\",
2061 architecture
, driver
->version
);
2066 #define gen_full_driver_unc_path(ctx, directory, file) \
2068 if (file && strlen(file)) { \
2069 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2071 file = talloc_strdup(ctx, ""); \
2074 return (uint32_t)-1; \
2078 /* .inf files do not always list a file for each of the four standard files.
2079 * Don't prepend a path to a null filename, or client claims:
2080 * "The server on which the printer resides does not have a suitable
2081 * <printer driver name> printer driver installed. Click OK if you
2082 * wish to install the driver on your local machine."
2085 gen_full_driver_unc_path(ctx
, directory
, driver
->driver_path
);
2086 gen_full_driver_unc_path(ctx
, directory
, driver
->data_file
);
2087 gen_full_driver_unc_path(ctx
, directory
, driver
->config_file
);
2088 gen_full_driver_unc_path(ctx
, directory
, driver
->help_file
);
2090 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
2091 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
2092 gen_full_driver_unc_path(ctx
, directory
,
2093 driver
->dependent_files
->string
[i
]);
2097 key
= talloc_asprintf(ctx
, "%s%s/%d/%s", DRIVERS_PREFIX
,
2098 architecture
, driver
->version
, driver
->driver_name
);
2103 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key
));
2110 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
2112 driver
->driver_name
,
2113 driver
->architecture
,
2114 driver
->driver_path
,
2116 driver
->config_file
,
2118 driver
->monitor_name
? driver
->monitor_name
: "",
2119 driver
->default_datatype
? driver
->default_datatype
: "");
2121 if (driver
->dependent_files
&& driver
->dependent_files
->string
) {
2122 for (i
=0; driver
->dependent_files
->string
[i
]; i
++) {
2123 len
+= tdb_pack(buf
+len
, buflen
-len
, "f",
2124 driver
->dependent_files
->string
[i
]);
2128 if (len
!= buflen
) {
2129 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
2131 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2142 ret
= tdb_store_bystring(tdb_drivers
, key
, dbuf
, TDB_REPLACE
);
2146 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
2152 /****************************************************************************
2153 ****************************************************************************/
2155 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8
*driver
)
2157 TALLOC_CTX
*mem_ctx
= talloc_new(talloc_tos());
2158 struct spoolss_AddDriverInfo3 info3
;
2161 convert_level_8_to_level3(mem_ctx
, &info3
, driver
);
2163 ret
= add_a_printer_driver_3(&info3
);
2164 talloc_free(mem_ctx
);
2169 /****************************************************************************
2170 ****************************************************************************/
2172 static WERROR
get_a_printer_driver_3_default(TALLOC_CTX
*mem_ctx
,
2173 struct spoolss_DriverInfo3
*info
,
2174 const char *driver
, const char *arch
)
2176 info
->driver_name
= talloc_strdup(mem_ctx
, driver
);
2177 if (!info
->driver_name
) {
2181 info
->default_datatype
= talloc_strdup(mem_ctx
, "RAW");
2182 if (!info
->default_datatype
) {
2186 info
->driver_path
= talloc_strdup(mem_ctx
, "");
2187 info
->data_file
= talloc_strdup(mem_ctx
, "");
2188 info
->config_file
= talloc_strdup(mem_ctx
, "");
2189 info
->help_file
= talloc_strdup(mem_ctx
, "");
2190 if (!info
->driver_path
|| !info
->data_file
|| !info
->config_file
|| !info
->help_file
) {
2197 /****************************************************************************
2198 ****************************************************************************/
2200 static WERROR
get_a_printer_driver_3(TALLOC_CTX
*mem_ctx
,
2201 struct spoolss_DriverInfo3
*driver
,
2202 const char *drivername
, const char *arch
,
2206 const char *architecture
;
2210 fstring name
, driverpath
, environment
, datafile
, configfile
, helpfile
, monitorname
, defaultdatatype
;
2212 architecture
= get_short_archi(arch
);
2213 if ( !architecture
) {
2214 return WERR_UNKNOWN_PRINTER_DRIVER
;
2217 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2219 if ( strcmp( architecture
, SPL_ARCH_WIN40
) == 0 )
2222 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX
, architecture
, version
, drivername
));
2224 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
2225 architecture
, version
, drivername
) < 0) {
2229 dbuf
= tdb_fetch_bystring(tdb_drivers
, key
);
2232 return WERR_UNKNOWN_PRINTER_DRIVER
;
2235 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
2246 driver
->driver_name
= talloc_strdup(mem_ctx
, name
);
2247 driver
->architecture
= talloc_strdup(mem_ctx
, environment
);
2248 driver
->driver_path
= talloc_strdup(mem_ctx
, driverpath
);
2249 driver
->data_file
= talloc_strdup(mem_ctx
, datafile
);
2250 driver
->config_file
= talloc_strdup(mem_ctx
, configfile
);
2251 driver
->help_file
= talloc_strdup(mem_ctx
, helpfile
);
2252 driver
->monitor_name
= talloc_strdup(mem_ctx
, monitorname
);
2253 driver
->default_datatype
= talloc_strdup(mem_ctx
, defaultdatatype
);
2257 while (len
< dbuf
.dsize
) {
2261 driver
->dependent_files
= talloc_realloc(mem_ctx
, driver
->dependent_files
, const char *, i
+2);
2262 if (!driver
->dependent_files
) {
2263 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2267 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
2270 driver
->dependent_files
[i
] = talloc_strdup(mem_ctx
, file
);
2275 if (driver
->dependent_files
)
2276 driver
->dependent_files
[i
] = NULL
;
2278 SAFE_FREE(dbuf
.dptr
);
2281 if (len
!= dbuf
.dsize
) {
2282 return get_a_printer_driver_3_default(mem_ctx
, driver
, drivername
, arch
);
2288 /****************************************************************************
2289 ****************************************************************************/
2290 int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, uint8
*buf
, int buflen
)
2294 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2299 len
+= tdb_pack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2300 nt_devmode
->devicename
,
2301 nt_devmode
->formname
,
2303 nt_devmode
->specversion
,
2304 nt_devmode
->driverversion
,
2306 nt_devmode
->driverextra
,
2307 nt_devmode
->orientation
,
2308 nt_devmode
->papersize
,
2309 nt_devmode
->paperlength
,
2310 nt_devmode
->paperwidth
,
2313 nt_devmode
->defaultsource
,
2314 nt_devmode
->printquality
,
2317 nt_devmode
->yresolution
,
2318 nt_devmode
->ttoption
,
2319 nt_devmode
->collate
,
2320 nt_devmode
->logpixels
,
2323 nt_devmode
->bitsperpel
,
2324 nt_devmode
->pelswidth
,
2325 nt_devmode
->pelsheight
,
2326 nt_devmode
->displayflags
,
2327 nt_devmode
->displayfrequency
,
2328 nt_devmode
->icmmethod
,
2329 nt_devmode
->icmintent
,
2330 nt_devmode
->mediatype
,
2331 nt_devmode
->dithertype
,
2332 nt_devmode
->reserved1
,
2333 nt_devmode
->reserved2
,
2334 nt_devmode
->panningwidth
,
2335 nt_devmode
->panningheight
,
2336 nt_devmode
->nt_dev_private
);
2338 if (nt_devmode
->nt_dev_private
) {
2339 len
+= tdb_pack(buf
+len
, buflen
-len
, "B",
2340 nt_devmode
->driverextra
,
2341 nt_devmode
->nt_dev_private
);
2344 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode
->formname
));
2349 /****************************************************************************
2350 Pack all values in all printer keys
2351 ***************************************************************************/
2353 static int pack_values(NT_PRINTER_DATA
*data
, uint8
*buf
, int buflen
)
2357 struct regval_blob
*val
;
2358 struct regval_ctr
*val_ctr
;
2365 /* loop over all keys */
2367 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2368 val_ctr
= data
->keys
[i
].values
;
2369 num_values
= regval_ctr_numvals( val_ctr
);
2371 /* pack the keyname followed by a empty value */
2373 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2374 &data
->keys
[i
].name
,
2380 /* now loop over all values */
2382 for ( j
=0; j
<num_values
; j
++ ) {
2383 /* pathname should be stored as <key>\<value> */
2385 val
= regval_ctr_specific_value( val_ctr
, j
);
2386 if (asprintf(&path
, "%s\\%s",
2388 regval_name(val
)) < 0) {
2392 len
+= tdb_pack(buf
+len
, buflen
-len
, "pPdB",
2397 regval_data_p(val
) );
2399 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val
), regval_size(val
)));
2407 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", NULL
);
2413 /****************************************************************************
2414 Delete a printer - this just deletes the printer info file, any open
2415 handles are not affected.
2416 ****************************************************************************/
2418 uint32
del_a_printer(const char *sharename
)
2421 char *printdb_path
= NULL
;
2422 TALLOC_CTX
*ctx
= talloc_tos();
2424 kbuf
= make_printer_tdbkey(ctx
, sharename
);
2425 tdb_delete(tdb_printers
, kbuf
);
2427 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
2428 tdb_delete(tdb_printers
, kbuf
);
2430 close_all_print_db();
2432 if (geteuid() == sec_initial_uid()) {
2433 if (asprintf(&printdb_path
, "%s%s.tdb",
2434 cache_path("printing/"),
2438 unlink(printdb_path
);
2439 SAFE_FREE(printdb_path
);
2445 /****************************************************************************
2446 ****************************************************************************/
2447 static WERROR
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
2453 TDB_DATA kbuf
, dbuf
;
2456 * in addprinter: no servername and the printer is the name
2457 * in setprinter: servername is \\server
2458 * and printer is \\server\\printer
2460 * Samba manages only local printers.
2461 * we currently don't support things like i
2462 * path=\\other_server\printer
2464 * We only store the printername, not \\server\printername
2467 if ( info
->servername
[0] != '\0' ) {
2468 trim_string(info
->printername
, info
->servername
, NULL
);
2469 trim_char(info
->printername
, '\\', '\0');
2470 info
->servername
[0]='\0';
2474 * JFM: one day I'll forget.
2475 * below that's info->portname because that's the SAMBA sharename
2476 * and I made NT 'thinks' it's the portname
2477 * the info->sharename is the thing you can name when you add a printer
2478 * that's the short-name when you create shared printer for 95/98
2479 * So I've made a limitation in SAMBA: you can only have 1 printer model
2480 * behind a SAMBA share.
2488 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
2491 info
->default_priority
,
2508 info
->printprocessor
,
2512 len
+= pack_devicemode(info
->devmode
, buf
+len
, buflen
-len
);
2513 retlen
= pack_values( info
->data
, buf
+len
, buflen
-len
);
2520 if (buflen
!= len
) {
2521 buf
= (uint8
*)SMB_REALLOC(buf
, len
);
2523 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2531 kbuf
= make_printer_tdbkey(talloc_tos(), info
->sharename
);
2536 ret
= (tdb_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
) == 0? WERR_OK
: WERR_NOMEM
);
2539 if (!W_ERROR_IS_OK(ret
))
2540 DEBUG(8, ("error updating printer to tdb on disk\n"));
2544 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2545 info
->sharename
, info
->drivername
, info
->portname
, len
));
2550 /****************************************************************************
2551 Create and allocate a default devicemode.
2552 ****************************************************************************/
2554 WERROR
spoolss_create_default_devmode(TALLOC_CTX
*mem_ctx
,
2555 const char *devicename
,
2556 struct spoolss_DeviceMode
**devmode
)
2558 struct spoolss_DeviceMode
*dm
;
2561 dm
= talloc_zero(mem_ctx
, struct spoolss_DeviceMode
);
2566 dname
= talloc_asprintf(dm
, "%s", devicename
);
2567 if (dname
== NULL
) {
2570 if (strlen(dname
) > MAXDEVICENAME
) {
2571 dname
[MAXDEVICENAME
] = '\0';
2573 dm
->devicename
= dname
;
2575 dm
->formname
= talloc_strdup(dm
, "Letter");
2576 if (dm
->formname
== NULL
) {
2580 dm
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2581 dm
->driverversion
= 0x0400;
2583 dm
->__driverextra_length
= 0;
2584 dm
->fields
= DEVMODE_FORMNAME
|
2586 DEVMODE_PRINTQUALITY
|
2587 DEVMODE_DEFAULTSOURCE
|
2591 DEVMODE_ORIENTATION
;
2592 dm
->orientation
= DMORIENT_PORTRAIT
;
2593 dm
->papersize
= DMPAPER_LETTER
;
2594 dm
->paperlength
= 0;
2598 dm
->defaultsource
= DMBIN_FORMSOURCE
;
2599 dm
->printquality
= DMRES_HIGH
; /* 0x0258 */
2600 dm
->color
= DMRES_MONOCHROME
;
2601 dm
->duplex
= DMDUP_SIMPLEX
;
2602 dm
->yresolution
= 0;
2603 dm
->ttoption
= DMTT_SUBDEV
;
2604 dm
->collate
= DMCOLLATE_FALSE
;
2614 dm
->displayflags
= 0;
2615 dm
->displayfrequency
= 0;
2618 dm
->panningwidth
= 0;
2619 dm
->panningheight
= 0;
2621 dm
->driverextra_data
.data
= NULL
;
2622 dm
->driverextra_data
.length
= 0;
2628 WERROR
spoolss_create_default_secdesc(TALLOC_CTX
*mem_ctx
,
2629 struct spoolss_security_descriptor
**secdesc
)
2631 struct security_ace ace
[5]; /* max number of ace entries */
2634 struct security_acl
*psa
= NULL
;
2635 struct security_descriptor
*psd
= NULL
;
2636 struct dom_sid adm_sid
;
2639 /* Create an ACE where Everyone is allowed to print */
2641 sa
= PRINTER_ACE_PRINT
;
2642 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2643 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2645 /* Add the domain admins group if we are a DC */
2648 struct dom_sid domadmins_sid
;
2650 sid_compose(&domadmins_sid
, get_global_sam_sid(),
2653 sa
= PRINTER_ACE_FULL_CONTROL
;
2654 init_sec_ace(&ace
[i
++], &domadmins_sid
,
2655 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2656 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2657 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2658 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2660 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
2661 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
2663 sa
= PRINTER_ACE_FULL_CONTROL
;
2664 init_sec_ace(&ace
[i
++], &adm_sid
,
2665 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2666 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2667 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
2668 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2671 /* add BUILTIN\Administrators as FULL CONTROL */
2673 sa
= PRINTER_ACE_FULL_CONTROL
;
2674 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2675 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
2676 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
2677 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
2678 SEC_ACE_TYPE_ACCESS_ALLOWED
,
2679 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
2681 /* Make the security descriptor owned by the BUILTIN\Administrators */
2683 /* The ACL revision number in rpc_secdesc.h differs from the one
2684 created by NT when setting ACE entries in printer
2685 descriptors. NT4 complains about the property being edited by a
2688 if ((psa
= make_sec_acl(mem_ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
2689 psd
= make_sec_desc(mem_ctx
,
2691 SEC_DESC_SELF_RELATIVE
,
2692 &global_sid_Builtin_Administrators
,
2693 &global_sid_Builtin_Administrators
,
2700 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2704 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2705 (unsigned int)sd_size
));
2712 /****************************************************************************
2713 Malloc and return an NT devicemode.
2714 ****************************************************************************/
2716 NT_DEVICEMODE
*construct_nt_devicemode(const fstring default_devicename
)
2719 char adevice
[MAXDEVICENAME
];
2720 NT_DEVICEMODE
*nt_devmode
= SMB_MALLOC_P(NT_DEVICEMODE
);
2722 if (nt_devmode
== NULL
) {
2723 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2727 ZERO_STRUCTP(nt_devmode
);
2729 slprintf(adevice
, sizeof(adevice
), "%s", default_devicename
);
2730 fstrcpy(nt_devmode
->devicename
, adevice
);
2732 fstrcpy(nt_devmode
->formname
, "Letter");
2734 nt_devmode
->specversion
= DMSPEC_NT4_AND_ABOVE
;
2735 nt_devmode
->driverversion
= 0x0400;
2736 nt_devmode
->size
= 0x00DC;
2737 nt_devmode
->driverextra
= 0x0000;
2738 nt_devmode
->fields
= DEVMODE_FORMNAME
|
2740 DEVMODE_PRINTQUALITY
|
2741 DEVMODE_DEFAULTSOURCE
|
2745 DEVMODE_ORIENTATION
;
2746 nt_devmode
->orientation
= DMORIENT_PORTRAIT
;
2747 nt_devmode
->papersize
= DMPAPER_LETTER
;
2748 nt_devmode
->paperlength
= 0;
2749 nt_devmode
->paperwidth
= 0;
2750 nt_devmode
->scale
= 0x64;
2751 nt_devmode
->copies
= 1;
2752 nt_devmode
->defaultsource
= DMBIN_FORMSOURCE
;
2753 nt_devmode
->printquality
= DMRES_HIGH
; /* 0x0258 */
2754 nt_devmode
->color
= DMRES_MONOCHROME
;
2755 nt_devmode
->duplex
= DMDUP_SIMPLEX
;
2756 nt_devmode
->yresolution
= 0;
2757 nt_devmode
->ttoption
= DMTT_SUBDEV
;
2758 nt_devmode
->collate
= DMCOLLATE_FALSE
;
2759 nt_devmode
->icmmethod
= 0;
2760 nt_devmode
->icmintent
= 0;
2761 nt_devmode
->mediatype
= 0;
2762 nt_devmode
->dithertype
= 0;
2764 /* non utilisés par un driver d'imprimante */
2765 nt_devmode
->logpixels
= 0;
2766 nt_devmode
->bitsperpel
= 0;
2767 nt_devmode
->pelswidth
= 0;
2768 nt_devmode
->pelsheight
= 0;
2769 nt_devmode
->displayflags
= 0;
2770 nt_devmode
->displayfrequency
= 0;
2771 nt_devmode
->reserved1
= 0;
2772 nt_devmode
->reserved2
= 0;
2773 nt_devmode
->panningwidth
= 0;
2774 nt_devmode
->panningheight
= 0;
2776 nt_devmode
->nt_dev_private
= NULL
;
2780 /****************************************************************************
2781 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2782 ****************************************************************************/
2784 void free_nt_devicemode(NT_DEVICEMODE
**devmode_ptr
)
2786 NT_DEVICEMODE
*nt_devmode
= *devmode_ptr
;
2788 if(nt_devmode
== NULL
)
2791 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2793 SAFE_FREE(nt_devmode
->nt_dev_private
);
2794 SAFE_FREE(*devmode_ptr
);
2797 /****************************************************************************
2798 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2799 ****************************************************************************/
2801 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
)
2803 NT_PRINTER_INFO_LEVEL_2
*info
= *info_ptr
;
2808 free_nt_devicemode(&info
->devmode
);
2810 TALLOC_FREE( *info_ptr
);
2814 /****************************************************************************
2815 ****************************************************************************/
2816 int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, const uint8
*buf
, int buflen
)
2820 NT_DEVICEMODE devmode
;
2822 ZERO_STRUCT(devmode
);
2824 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", nt_devmode
);
2826 if (!*nt_devmode
) return len
;
2828 len
+= tdb_unpack(buf
+len
, buflen
-len
, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2832 &devmode
.specversion
,
2833 &devmode
.driverversion
,
2835 &devmode
.driverextra
,
2836 &devmode
.orientation
,
2838 &devmode
.paperlength
,
2839 &devmode
.paperwidth
,
2842 &devmode
.defaultsource
,
2843 &devmode
.printquality
,
2846 &devmode
.yresolution
,
2852 &devmode
.bitsperpel
,
2854 &devmode
.pelsheight
,
2855 &devmode
.displayflags
,
2856 &devmode
.displayfrequency
,
2860 &devmode
.dithertype
,
2863 &devmode
.panningwidth
,
2864 &devmode
.panningheight
,
2865 &devmode
.nt_dev_private
);
2867 if (devmode
.nt_dev_private
) {
2868 /* the len in tdb_unpack is an int value and
2869 * devmode.driverextra is only a short
2871 len
+= tdb_unpack(buf
+len
, buflen
-len
, "B", &extra_len
, &devmode
.nt_dev_private
);
2872 devmode
.driverextra
=(uint16
)extra_len
;
2874 /* check to catch an invalid TDB entry so we don't segfault */
2875 if (devmode
.driverextra
== 0) {
2876 devmode
.nt_dev_private
= NULL
;
2880 *nt_devmode
= (NT_DEVICEMODE
*)memdup(&devmode
, sizeof(devmode
));
2882 SAFE_FREE(devmode
.nt_dev_private
);
2886 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode
.devicename
, devmode
.formname
));
2887 if (devmode
.nt_dev_private
)
2888 DEBUG(8,("with a private section of %d bytes\n", devmode
.driverextra
));
2893 /****************************************************************************
2894 Allocate and initialize a new slot.
2895 ***************************************************************************/
2897 int add_new_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2903 if ( !name
|| !data
)
2906 /* allocate another slot in the NT_PRINTER_KEY array */
2908 if ( !(d
= TALLOC_REALLOC_ARRAY( data
, data
->keys
, NT_PRINTER_KEY
, data
->num_keys
+1)) ) {
2909 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2915 key_index
= data
->num_keys
;
2917 /* initialze new key */
2919 data
->keys
[key_index
].name
= talloc_strdup( data
, name
);
2921 werr
= regval_ctr_init(data
, &(data
->keys
[key_index
].values
));
2922 if (!W_ERROR_IS_OK(werr
)) {
2928 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name
));
2933 /****************************************************************************
2934 search for a registry key name in the existing printer data
2935 ***************************************************************************/
2937 int delete_printer_key( NT_PRINTER_DATA
*data
, const char *name
)
2941 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2942 if ( strequal( data
->keys
[i
].name
, name
) ) {
2944 /* cleanup memory */
2946 TALLOC_FREE( data
->keys
[i
].name
);
2947 TALLOC_FREE( data
->keys
[i
].values
);
2949 /* if not the end of the array, move remaining elements down one slot */
2952 if ( data
->num_keys
&& (i
< data
->num_keys
) )
2953 memmove( &data
->keys
[i
], &data
->keys
[i
+1], sizeof(NT_PRINTER_KEY
)*(data
->num_keys
-i
) );
2960 return data
->num_keys
;
2963 /****************************************************************************
2964 search for a registry key name in the existing printer data
2965 ***************************************************************************/
2967 int lookup_printerkey( NT_PRINTER_DATA
*data
, const char *name
)
2972 if ( !data
|| !name
)
2975 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name
));
2977 /* loop over all existing keys */
2979 for ( i
=0; i
<data
->num_keys
; i
++ ) {
2980 if ( strequal(data
->keys
[i
].name
, name
) ) {
2981 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name
));
2991 /****************************************************************************
2992 ***************************************************************************/
2994 int get_printer_subkeys( NT_PRINTER_DATA
*data
, const char* key
, fstring
**subkeys
)
2998 int num_subkeys
= 0;
3000 fstring
*subkeys_ptr
= NULL
;
3011 /* special case of asking for the top level printer data registry key names */
3013 if ( strlen(key
) == 0 ) {
3014 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3016 /* found a match, so allocate space and copy the name */
3018 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
3019 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3024 fstrcpy( subkeys_ptr
[num_subkeys
], data
->keys
[i
].name
);
3031 /* asking for the subkeys of some key */
3032 /* subkey paths are stored in the key name using '\' as the delimiter */
3034 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3035 if ( StrnCaseCmp(data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3037 /* if we found the exact key, then break */
3038 key_len
= strlen( key
);
3039 if ( strlen(data
->keys
[i
].name
) == key_len
)
3042 /* get subkey path */
3044 p
= data
->keys
[i
].name
+ key_len
;
3047 fstrcpy( subkeyname
, p
);
3048 if ( (p
= strchr( subkeyname
, '\\' )) )
3051 /* don't add a key more than once */
3053 for ( j
=0; j
<num_subkeys
; j
++ ) {
3054 if ( strequal( subkeys_ptr
[j
], subkeyname
) )
3058 if ( j
!= num_subkeys
)
3061 /* found a match, so allocate space and copy the name */
3063 if ( !(subkeys_ptr
= SMB_REALLOC_ARRAY( subkeys_ptr
, fstring
, num_subkeys
+2)) ) {
3064 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3069 fstrcpy( subkeys_ptr
[num_subkeys
], subkeyname
);
3075 /* return error if the key was not found */
3077 if ( i
== data
->num_keys
) {
3078 SAFE_FREE(subkeys_ptr
);
3083 /* tag off the end */
3086 fstrcpy(subkeys_ptr
[num_subkeys
], "" );
3088 *subkeys
= subkeys_ptr
;
3094 static void map_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3097 regval_ctr_delvalue(ctr
, val_name
);
3098 regval_ctr_addvalue_sz(ctr
, val_name
, sz
);
3101 static void map_dword_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3104 regval_ctr_delvalue(ctr
, val_name
);
3105 regval_ctr_addvalue(ctr
, val_name
, REG_DWORD
,
3106 (uint8
*) &dword
, sizeof(dword
));
3109 static void map_bool_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3112 uint8 bin_bool
= (b
? 1 : 0);
3113 regval_ctr_delvalue(ctr
, val_name
);
3114 regval_ctr_addvalue(ctr
, val_name
, REG_BINARY
,
3115 (uint8
*) &bin_bool
, sizeof(bin_bool
));
3118 static void map_single_multi_sz_into_ctr(struct regval_ctr
*ctr
, const char *val_name
,
3119 const char *multi_sz
)
3126 regval_ctr_delvalue(ctr
, val_name
);
3127 regval_ctr_addvalue_multi_sz(ctr
, val_name
, a
);
3130 /****************************************************************************
3131 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3133 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3134 * @return bool indicating success or failure
3135 ***************************************************************************/
3137 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2
*info2
)
3139 struct regval_ctr
*ctr
= NULL
;
3141 const char *dnssuffix
;
3142 char *allocated_string
= NULL
;
3143 const char *ascii_str
;
3146 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3147 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3148 ctr
= info2
->data
->keys
[i
].values
;
3150 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTERNAME
, info2
->sharename
);
3151 map_sz_into_ctr(ctr
, SPOOL_REG_SHORTSERVERNAME
, global_myname());
3153 /* we make the assumption that the netbios name is the same
3154 as the DNS name sinc ethe former will be what we used to
3157 dnssuffix
= get_mydnsdomname(talloc_tos());
3158 if (dnssuffix
&& *dnssuffix
) {
3159 fstr_sprintf( longname
, "%s.%s", global_myname(), dnssuffix
);
3161 fstrcpy( longname
, global_myname() );
3164 map_sz_into_ctr(ctr
, SPOOL_REG_SERVERNAME
, longname
);
3166 if (asprintf(&allocated_string
, "\\\\%s\\%s", longname
, info2
->sharename
) == -1) {
3169 map_sz_into_ctr(ctr
, SPOOL_REG_UNCNAME
, allocated_string
);
3170 SAFE_FREE(allocated_string
);
3172 map_dword_into_ctr(ctr
, SPOOL_REG_VERSIONNUMBER
, 4);
3173 map_sz_into_ctr(ctr
, SPOOL_REG_DRIVERNAME
, info2
->drivername
);
3174 map_sz_into_ctr(ctr
, SPOOL_REG_LOCATION
, info2
->location
);
3175 map_sz_into_ctr(ctr
, SPOOL_REG_DESCRIPTION
, info2
->comment
);
3176 map_single_multi_sz_into_ctr(ctr
, SPOOL_REG_PORTNAME
, info2
->portname
);
3177 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSEPARATORFILE
, info2
->sepfile
);
3178 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTSTARTTIME
, info2
->starttime
);
3179 map_dword_into_ctr(ctr
, SPOOL_REG_PRINTENDTIME
, info2
->untiltime
);
3180 map_dword_into_ctr(ctr
, SPOOL_REG_PRIORITY
, info2
->priority
);
3182 map_bool_into_ctr(ctr
, SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
3183 (info2
->attributes
&
3184 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
3186 switch (info2
->attributes
& 0x3) {
3188 ascii_str
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
3191 ascii_str
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
3194 ascii_str
= SPOOL_REGVAL_PRINTDIRECT
;
3197 ascii_str
= "unknown";
3199 map_sz_into_ctr(ctr
, SPOOL_REG_PRINTSPOOLING
, ascii_str
);
3204 /*****************************************************************
3205 ****************************************************************/
3207 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2
*info2
,
3211 struct regval_ctr
*ctr
=NULL
;
3213 /* find the DsSpooler key */
3214 if ((i
= lookup_printerkey(info2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0)
3215 i
= add_new_printer_key(info2
->data
, SPOOL_DSSPOOLER_KEY
);
3216 ctr
= info2
->data
->keys
[i
].values
;
3218 regval_ctr_delvalue(ctr
, "objectGUID");
3220 /* We used to store this as a REG_BINARY but that causes
3223 regval_ctr_addvalue_sz(ctr
, "objectGUID",
3224 GUID_string(talloc_tos(), &guid
));
3227 static WERROR
nt_printer_publish_ads(ADS_STRUCT
*ads
,
3228 NT_PRINTER_INFO_LEVEL
*printer
)
3232 char *prt_dn
= NULL
, *srv_dn
, *srv_cn_0
, *srv_cn_escaped
, *sharename_escaped
;
3233 char *srv_dn_utf8
, **srv_cn_utf8
;
3236 const char *attrs
[] = {"objectGUID", NULL
};
3238 WERROR win_rc
= WERR_OK
;
3239 size_t converted_size
;
3241 /* build the ads mods */
3242 ctx
= talloc_init("nt_printer_publish_ads");
3247 DEBUG(5, ("publishing printer %s\n", printer
->info_2
->printername
));
3249 /* figure out where to publish */
3250 ads_find_machine_acct(ads
, &res
, global_myname());
3252 /* We use ldap_get_dn here as we need the answer
3253 * in utf8 to call ldap_explode_dn(). JRA. */
3255 srv_dn_utf8
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
3258 return WERR_SERVER_UNAVAILABLE
;
3260 ads_msgfree(ads
, res
);
3261 srv_cn_utf8
= ldap_explode_dn(srv_dn_utf8
, 1);
3264 ldap_memfree(srv_dn_utf8
);
3265 return WERR_SERVER_UNAVAILABLE
;
3267 /* Now convert to CH_UNIX. */
3268 if (!pull_utf8_talloc(ctx
, &srv_dn
, srv_dn_utf8
, &converted_size
)) {
3270 ldap_memfree(srv_dn_utf8
);
3271 ldap_memfree(srv_cn_utf8
);
3272 return WERR_SERVER_UNAVAILABLE
;
3274 if (!pull_utf8_talloc(ctx
, &srv_cn_0
, srv_cn_utf8
[0], &converted_size
)) {
3276 ldap_memfree(srv_dn_utf8
);
3277 ldap_memfree(srv_cn_utf8
);
3278 TALLOC_FREE(srv_dn
);
3279 return WERR_SERVER_UNAVAILABLE
;
3282 ldap_memfree(srv_dn_utf8
);
3283 ldap_memfree(srv_cn_utf8
);
3285 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn_0
);
3286 if (!srv_cn_escaped
) {
3288 return WERR_SERVER_UNAVAILABLE
;
3290 sharename_escaped
= escape_rdn_val_string_alloc(printer
->info_2
->sharename
);
3291 if (!sharename_escaped
) {
3292 SAFE_FREE(srv_cn_escaped
);
3294 return WERR_SERVER_UNAVAILABLE
;
3297 prt_dn
= talloc_asprintf(ctx
, "cn=%s-%s,%s", srv_cn_escaped
, sharename_escaped
, srv_dn
);
3299 SAFE_FREE(srv_cn_escaped
);
3300 SAFE_FREE(sharename_escaped
);
3302 mods
= ads_init_mods(ctx
);
3310 get_local_printer_publishing_data(ctx
, &mods
, printer
->info_2
->data
);
3311 ads_mod_str(ctx
, &mods
, SPOOL_REG_PRINTERNAME
,
3312 printer
->info_2
->sharename
);
3315 ads_rc
= ads_mod_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3316 if (ads_rc
.err
.rc
== LDAP_NO_SUCH_OBJECT
) {
3318 for (i
=0; mods
[i
] != 0; i
++)
3320 mods
[i
] = (LDAPMod
*)-1;
3321 ads_rc
= ads_add_printer_entry(ads
, prt_dn
, ctx
, &mods
);
3324 if (!ADS_ERR_OK(ads_rc
))
3325 DEBUG(3, ("error publishing %s: %s\n", printer
->info_2
->sharename
, ads_errstr(ads_rc
)));
3327 /* retreive the guid and store it locally */
3328 if (ADS_ERR_OK(ads_search_dn(ads
, &res
, prt_dn
, attrs
))) {
3330 ads_pull_guid(ads
, res
, &guid
);
3331 ads_msgfree(ads
, res
);
3332 store_printer_guid(printer
->info_2
, guid
);
3333 win_rc
= mod_a_printer(printer
, 2);
3340 static WERROR
nt_printer_unpublish_ads(ADS_STRUCT
*ads
,
3341 NT_PRINTER_INFO_LEVEL
*printer
)
3344 LDAPMessage
*res
= NULL
;
3345 char *prt_dn
= NULL
;
3347 DEBUG(5, ("unpublishing printer %s\n", printer
->info_2
->printername
));
3349 /* remove the printer from the directory */
3350 ads_rc
= ads_find_printer_on_server(ads
, &res
,
3351 printer
->info_2
->sharename
, global_myname());
3353 if (ADS_ERR_OK(ads_rc
) && res
&& ads_count_replies(ads
, res
)) {
3354 prt_dn
= ads_get_dn(ads
, talloc_tos(), res
);
3356 ads_msgfree(ads
, res
);
3359 ads_rc
= ads_del_dn(ads
, prt_dn
);
3360 TALLOC_FREE(prt_dn
);
3364 ads_msgfree(ads
, res
);
3369 /****************************************************************************
3370 * Publish a printer in the directory
3372 * @param snum describing printer service
3373 * @return WERROR indicating status of publishing
3374 ***************************************************************************/
3376 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3379 ADS_STRUCT
*ads
= NULL
;
3380 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3383 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3384 if (!W_ERROR_IS_OK(win_rc
))
3388 case DSPRINT_PUBLISH
:
3389 case DSPRINT_UPDATE
:
3390 /* set the DsSpooler info and attributes */
3391 if (!(map_nt_printer_info2_to_dsspooler(printer
->info_2
))) {
3392 win_rc
= WERR_NOMEM
;
3396 printer
->info_2
->attributes
|= PRINTER_ATTRIBUTE_PUBLISHED
;
3398 case DSPRINT_UNPUBLISH
:
3399 printer
->info_2
->attributes
^= PRINTER_ATTRIBUTE_PUBLISHED
;
3402 win_rc
= WERR_NOT_SUPPORTED
;
3406 win_rc
= mod_a_printer(printer
, 2);
3407 if (!W_ERROR_IS_OK(win_rc
)) {
3408 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc
)));
3412 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3414 DEBUG(3, ("ads_init() failed\n"));
3415 win_rc
= WERR_SERVER_UNAVAILABLE
;
3418 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3419 SAFE_FREE(ads
->auth
.password
);
3420 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3423 /* ads_connect() will find the DC for us */
3424 ads_rc
= ads_connect(ads
);
3425 if (!ADS_ERR_OK(ads_rc
)) {
3426 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3427 win_rc
= WERR_ACCESS_DENIED
;
3432 case DSPRINT_PUBLISH
:
3433 case DSPRINT_UPDATE
:
3434 win_rc
= nt_printer_publish_ads(ads
, printer
);
3436 case DSPRINT_UNPUBLISH
:
3437 win_rc
= nt_printer_unpublish_ads(ads
, printer
);
3442 free_a_printer(&printer
, 2);
3447 WERROR
check_published_printers(void)
3450 ADS_STRUCT
*ads
= NULL
;
3452 int n_services
= lp_numservices();
3453 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3455 ads
= ads_init(lp_realm(), lp_workgroup(), NULL
);
3457 DEBUG(3, ("ads_init() failed\n"));
3458 return WERR_SERVER_UNAVAILABLE
;
3460 setenv(KRB5_ENV_CCNAME
, "MEMORY:prtpub_cache", 1);
3461 SAFE_FREE(ads
->auth
.password
);
3462 ads
->auth
.password
= secrets_fetch_machine_password(lp_workgroup(),
3465 /* ads_connect() will find the DC for us */
3466 ads_rc
= ads_connect(ads
);
3467 if (!ADS_ERR_OK(ads_rc
)) {
3468 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc
)));
3470 ads_kdestroy("MEMORY:prtpub_cache");
3471 return WERR_ACCESS_DENIED
;
3474 for (snum
= 0; snum
< n_services
; snum
++) {
3475 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
)))
3478 if (W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2,
3479 lp_servicename(snum
))) &&
3480 (printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
))
3481 nt_printer_publish_ads(ads
, printer
);
3483 free_a_printer(&printer
, 2);
3487 ads_kdestroy("MEMORY:prtpub_cache");
3491 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3494 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3495 struct regval_ctr
*ctr
;
3496 struct regval_blob
*guid_val
;
3502 win_rc
= get_a_printer(print_hnd
, &printer
, 2, lp_servicename(snum
));
3504 if (!W_ERROR_IS_OK(win_rc
) ||
3505 !(printer
->info_2
->attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) ||
3506 ((i
= lookup_printerkey(printer
->info_2
->data
, SPOOL_DSSPOOLER_KEY
)) < 0) ||
3507 !(ctr
= printer
->info_2
->data
->keys
[i
].values
) ||
3508 !(guid_val
= regval_ctr_getvalue(ctr
, "objectGUID")))
3510 free_a_printer(&printer
, 2);
3514 /* fetching printer guids really ought to be a separate function. */
3519 /* We used to store the guid as REG_BINARY, then swapped
3520 to REG_SZ for Vista compatibility so check for both */
3522 switch ( regval_type(guid_val
) ){
3524 blob
= data_blob_const(regval_data_p(guid_val
),
3525 regval_size(guid_val
));
3526 pull_reg_sz(talloc_tos(), &blob
, (const char **)&guid_str
);
3527 ret
= NT_STATUS_IS_OK(GUID_from_string( guid_str
, guid
));
3528 talloc_free(guid_str
);
3531 if ( regval_size(guid_val
) != sizeof(struct GUID
) ) {
3535 memcpy(guid
, regval_data_p(guid_val
), sizeof(struct GUID
));
3538 DEBUG(0,("is_printer_published: GUID value stored as "
3539 "invaluid type (%d)\n", regval_type(guid_val
) ));
3544 free_a_printer(&printer
, 2);
3548 WERROR
nt_printer_publish(Printer_entry
*print_hnd
, int snum
, int action
)
3553 WERROR
check_published_printers(void)
3558 bool is_printer_published(Printer_entry
*print_hnd
, int snum
,
3563 #endif /* HAVE_ADS */
3565 /****************************************************************************
3566 ***************************************************************************/
3568 WERROR
delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
)
3570 NT_PRINTER_DATA
*data
;
3572 int removed_keys
= 0;
3576 empty_slot
= data
->num_keys
;
3579 return WERR_INVALID_PARAM
;
3581 /* remove all keys */
3583 if ( !strlen(key
) ) {
3585 TALLOC_FREE( data
);
3589 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3595 /* remove a specific key (and all subkeys) */
3597 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3598 if ( StrnCaseCmp( data
->keys
[i
].name
, key
, strlen(key
)) == 0 ) {
3599 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3600 data
->keys
[i
].name
));
3602 TALLOC_FREE( data
->keys
[i
].name
);
3603 TALLOC_FREE( data
->keys
[i
].values
);
3605 /* mark the slot as empty */
3607 ZERO_STRUCTP( &data
->keys
[i
] );
3611 /* find the first empty slot */
3613 for ( i
=0; i
<data
->num_keys
; i
++ ) {
3614 if ( !data
->keys
[i
].name
) {
3621 if ( i
== data
->num_keys
)
3622 /* nothing was removed */
3623 return WERR_INVALID_PARAM
;
3625 /* move everything down */
3627 for ( i
=empty_slot
+1; i
<data
->num_keys
; i
++ ) {
3628 if ( data
->keys
[i
].name
) {
3629 memcpy( &data
->keys
[empty_slot
], &data
->keys
[i
], sizeof(NT_PRINTER_KEY
) );
3630 ZERO_STRUCTP( &data
->keys
[i
] );
3638 data
->num_keys
-= removed_keys
;
3640 /* sanity check to see if anything is left */
3642 if ( !data
->num_keys
) {
3643 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2
->printername
));
3645 SAFE_FREE( data
->keys
);
3646 ZERO_STRUCTP( data
);
3652 /****************************************************************************
3653 ***************************************************************************/
3655 WERROR
delete_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3657 WERROR result
= WERR_OK
;
3660 /* we must have names on non-zero length */
3662 if ( !key
|| !*key
|| !value
|| !*value
)
3663 return WERR_INVALID_NAME
;
3665 /* find the printer key first */
3667 key_index
= lookup_printerkey( p2
->data
, key
);
3668 if ( key_index
== -1 )
3671 /* make sure the value exists so we can return the correct error code */
3673 if ( !regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
) )
3674 return WERR_BADFILE
;
3676 regval_ctr_delvalue( p2
->data
->keys
[key_index
].values
, value
);
3678 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3684 /****************************************************************************
3685 ***************************************************************************/
3687 WERROR
add_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
,
3688 uint32 type
, uint8
*data
, int real_len
)
3690 WERROR result
= WERR_OK
;
3693 /* we must have names on non-zero length */
3695 if ( !key
|| !*key
|| !value
|| !*value
)
3696 return WERR_INVALID_NAME
;
3698 /* find the printer key first */
3700 key_index
= lookup_printerkey( p2
->data
, key
);
3701 if ( key_index
== -1 )
3702 key_index
= add_new_printer_key( p2
->data
, key
);
3704 if ( key_index
== -1 )
3707 regval_ctr_addvalue( p2
->data
->keys
[key_index
].values
, value
,
3708 type
, data
, real_len
);
3710 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3711 key
, value
, type
, real_len
));
3716 /****************************************************************************
3717 ***************************************************************************/
3719 struct regval_blob
* get_printer_data( NT_PRINTER_INFO_LEVEL_2
*p2
, const char *key
, const char *value
)
3723 if ( (key_index
= lookup_printerkey( p2
->data
, key
)) == -1 )
3726 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3729 return regval_ctr_getvalue( p2
->data
->keys
[key_index
].values
, value
);
3732 /****************************************************************************
3733 Unpack a list of registry values frem the TDB
3734 ***************************************************************************/
3736 static int unpack_values(NT_PRINTER_DATA
*printer_data
, const uint8
*buf
, int buflen
)
3741 const char *valuename
= NULL
;
3742 const char *keyname
= NULL
;
3746 struct regval_blob
*regval_p
;
3749 /* add the "PrinterDriverData" key first for performance reasons */
3751 add_new_printer_key( printer_data
, SPOOL_PRINTERDATA_KEY
);
3753 /* loop and unpack the rest of the registry values */
3757 /* check to see if there are any more registry values */
3760 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", ®val_p
);
3764 /* unpack the next regval */
3766 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
3772 /* lookup for subkey names which have a type of REG_NONE */
3773 /* there's no data with this entry */
3775 if ( type
== REG_NONE
) {
3776 if ( (key_index
=lookup_printerkey( printer_data
, string
)) == -1 )
3777 add_new_printer_key( printer_data
, string
);
3782 * break of the keyname from the value name.
3783 * Valuenames can have embedded '\'s so be careful.
3784 * only support one level of keys. See the
3785 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3789 str
= strchr_m( string
, '\\');
3791 /* Put in "PrinterDriverData" is no key specified */
3794 keyname
= SPOOL_PRINTERDATA_KEY
;
3803 /* see if we need a new key */
3805 if ( (key_index
=lookup_printerkey( printer_data
, keyname
)) == -1 )
3806 key_index
= add_new_printer_key( printer_data
, keyname
);
3808 if ( key_index
== -1 ) {
3809 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3814 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname
, valuename
, size
));
3816 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3817 Thanks to Martin Zielinski for the hint. */
3819 if ( type
== REG_BINARY
&&
3820 strequal( keyname
, SPOOL_DSSPOOLER_KEY
) &&
3821 strequal( valuename
, "objectGUID" ) )
3825 /* convert the GUID to a UNICODE string */
3827 memcpy( &guid
, data_p
, sizeof(struct GUID
) );
3829 regval_ctr_addvalue_sz(printer_data
->keys
[key_index
].values
,
3831 GUID_string(talloc_tos(), &guid
));
3836 regval_ctr_addvalue( printer_data
->keys
[key_index
].values
,
3837 valuename
, type
, data_p
,
3841 SAFE_FREE(data_p
); /* 'B' option to tdbpack does a malloc() */
3848 /****************************************************************************
3849 ***************************************************************************/
3851 static char *win_driver
;
3852 static char *os2_driver
;
3854 static const char *get_win_driver(void)
3856 if (win_driver
== NULL
) {
3862 static const char *get_os2_driver(void)
3864 if (os2_driver
== NULL
) {
3870 static bool set_driver_mapping(const char *from
, const char *to
)
3872 SAFE_FREE(win_driver
);
3873 SAFE_FREE(os2_driver
);
3875 win_driver
= SMB_STRDUP(from
);
3876 os2_driver
= SMB_STRDUP(to
);
3878 if (win_driver
== NULL
|| os2_driver
== NULL
) {
3879 SAFE_FREE(win_driver
);
3880 SAFE_FREE(os2_driver
);
3886 static void map_to_os2_driver(fstring drivername
)
3888 char *mapfile
= lp_os2_driver_map();
3889 char **lines
= NULL
;
3893 if (!strlen(drivername
))
3899 if (strequal(drivername
, get_win_driver())) {
3900 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3901 drivername
, get_os2_driver()));
3902 fstrcpy(drivername
, get_os2_driver());
3906 lines
= file_lines_load(mapfile
, &numlines
,0,NULL
);
3907 if (numlines
== 0 || lines
== NULL
) {
3908 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile
));
3913 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
3915 for( i
= 0; i
< numlines
; i
++) {
3916 char *nt_name
= lines
[i
];
3917 char *os2_name
= strchr(nt_name
,'=');
3924 while (isspace(*nt_name
))
3927 if (!*nt_name
|| strchr("#;",*nt_name
))
3931 int l
= strlen(nt_name
);
3932 while (l
&& isspace(nt_name
[l
-1])) {
3938 while (isspace(*os2_name
))
3942 int l
= strlen(os2_name
);
3943 while (l
&& isspace(os2_name
[l
-1])) {
3949 if (strequal(nt_name
,drivername
)) {
3950 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername
,os2_name
));
3951 set_driver_mapping(drivername
,os2_name
);
3952 fstrcpy(drivername
,os2_name
);
3964 * @brief Map a Windows driver to a OS/2 driver.
3966 * @param[in] mem_ctx The memory context to use.
3968 * @param[in,out] pdrivername The drivername of Windows to remap.
3970 * @return WERR_OK on success, a corresponding WERROR on failure.
3972 WERROR
spoolss_map_to_os2_driver(TALLOC_CTX
*mem_ctx
, const char **pdrivername
)
3974 const char *mapfile
= lp_os2_driver_map();
3975 char **lines
= NULL
;
3976 const char *drivername
;
3980 if (pdrivername
== NULL
|| *pdrivername
== NULL
|| *pdrivername
[0] == '\0') {
3981 return WERR_INVALID_PARAMETER
;
3984 drivername
= *pdrivername
;
3986 if (mapfile
[0] == '\0') {
3987 return WERR_BADFILE
;
3990 if (strequal(drivername
, get_win_driver())) {
3991 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3992 drivername
, get_os2_driver()));
3993 drivername
= talloc_strdup(mem_ctx
, get_os2_driver());
3994 if (drivername
== NULL
) {
3997 *pdrivername
= drivername
;
4001 lines
= file_lines_load(mapfile
, &numlines
, 0, NULL
);
4002 if (numlines
== 0 || lines
== NULL
) {
4003 DEBUG(0,("No entries in OS/2 driver map %s\n", mapfile
));
4008 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile
));
4010 for( i
= 0; i
< numlines
; i
++) {
4011 char *nt_name
= lines
[i
];
4012 char *os2_name
= strchr(nt_name
, '=');
4014 if (os2_name
== NULL
) {
4020 while (isspace(*nt_name
)) {
4024 if (*nt_name
== '\0' || strchr("#;", *nt_name
)) {
4029 int l
= strlen(nt_name
);
4030 while (l
&& isspace(nt_name
[l
- 1])) {
4036 while (isspace(*os2_name
)) {
4041 int l
= strlen(os2_name
);
4042 while (l
&& isspace(os2_name
[l
-1])) {
4048 if (strequal(nt_name
, drivername
)) {
4049 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername
,os2_name
));
4050 set_driver_mapping(drivername
, os2_name
);
4051 drivername
= talloc_strdup(mem_ctx
, os2_name
);
4053 if (drivername
== NULL
) {
4056 *pdrivername
= drivername
;
4065 /****************************************************************************
4066 Get a default printer info 2 struct.
4067 ****************************************************************************/
4069 static WERROR
get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2
*info
,
4070 const char *servername
,
4071 const char* sharename
,
4074 int snum
= lp_servicenumber(sharename
);
4076 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
4077 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
4078 servername
, sharename
);
4079 fstrcpy(info
->sharename
, sharename
);
4080 fstrcpy(info
->portname
, SAMBA_PRINTER_PORT_NAME
);
4082 /* by setting the driver name to an empty string, a local NT admin
4083 can now run the **local** APW to install a local printer driver
4084 for a Samba shared printer in 2.2. Without this, drivers **must** be
4085 installed on the Samba server for NT clients --jerry */
4086 #if 0 /* JERRY --do not uncomment-- */
4087 if (!*info
->drivername
)
4088 fstrcpy(info
->drivername
, "NO DRIVER AVAILABLE FOR THIS PRINTER");
4092 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info
->drivername
));
4094 strlcpy(info
->comment
, "", sizeof(info
->comment
));
4095 fstrcpy(info
->printprocessor
, "winprint");
4096 fstrcpy(info
->datatype
, "RAW");
4099 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
4100 /* Pull the location and comment strings from cups if we don't
4102 if ( !strlen(info
->location
) || !strlen(info
->comment
) ) {
4103 char *comment
= NULL
;
4104 char *location
= NULL
;
4105 if (cups_pull_comment_location(info
, info
->sharename
,
4106 &comment
, &location
)) {
4107 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4108 fstrcpy(info
->location
, location
);
4109 TALLOC_FREE(comment
);
4110 TALLOC_FREE(location
);
4116 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
4118 info
->starttime
= 0; /* Minutes since 12:00am GMT */
4119 info
->untiltime
= 0; /* Minutes since 12:00am GMT */
4121 info
->default_priority
= 1;
4122 info
->setuptime
= (uint32
)time(NULL
);
4125 * I changed this as I think it is better to have a generic
4126 * DEVMODE than to crash Win2k explorer.exe --jerry
4127 * See the HP Deskjet 990c Win2k drivers for an example.
4129 * However the default devmode appears to cause problems
4130 * with the HP CLJ 8500 PCL driver. Hence the addition of
4131 * the "default devmode" parameter --jerry 22/01/2002
4134 if (lp_default_devmode(snum
)) {
4135 if ((info
->devmode
= construct_nt_devicemode(info
->printername
)) == NULL
) {
4139 info
->devmode
= NULL
;
4142 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
4146 info
->data
= TALLOC_ZERO_P(info
, NT_PRINTER_DATA
);
4151 add_new_printer_key(info
->data
, SPOOL_PRINTERDATA_KEY
);
4157 free_nt_devicemode(&info
->devmode
);
4159 return WERR_ACCESS_DENIED
;
4162 /****************************************************************************
4163 ****************************************************************************/
4165 static WERROR
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
,
4166 const char *servername
,
4167 const char *sharename
,
4171 int snum
= lp_servicenumber(sharename
);
4172 TDB_DATA kbuf
, dbuf
;
4173 fstring printername
;
4174 char adevice
[MAXDEVICENAME
];
4175 char *comment
= NULL
;
4177 kbuf
= make_printer_tdbkey(talloc_tos(), sharename
);
4179 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
4181 return get_a_printer_2_default(info
, servername
,
4182 sharename
, get_loc_com
);
4185 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
4188 &info
->default_priority
,
4195 &info
->c_setprinter
,
4205 info
->printprocessor
,
4210 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4214 /* Samba has to have shared raw drivers. */
4215 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
4216 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
4218 /* Restore the stripped strings. */
4219 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", servername
);
4221 if ( lp_force_printername(snum
) ) {
4222 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, sharename
);
4224 slprintf(printername
, sizeof(printername
)-1, "\\\\%s\\%s", servername
, info
->printername
);
4227 fstrcpy(info
->printername
, printername
);
4230 if (get_loc_com
&& (enum printing_types
)lp_printing(snum
) == PRINT_CUPS
) {
4231 /* Pull the location and comment strings from cups if we don't
4233 if ( !strlen(info
->location
) || !strlen(info
->comment
) ) {
4234 char *location
= NULL
;
4236 if (cups_pull_comment_location(info
, info
->sharename
,
4237 &comment
, &location
)) {
4238 strlcpy(info
->comment
, comment
, sizeof(info
->comment
));
4239 fstrcpy(info
->location
, location
);
4240 TALLOC_FREE(comment
);
4241 TALLOC_FREE(location
);
4247 len
+= unpack_devicemode(&info
->devmode
,dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4250 * Some client drivers freak out if there is a NULL devmode
4251 * (probably the driver is not checking before accessing
4252 * the devmode pointer) --jerry
4254 * See comments in get_a_printer_2_default()
4257 if (lp_default_devmode(snum
) && !info
->devmode
) {
4258 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4260 info
->devmode
= construct_nt_devicemode(printername
);
4263 slprintf( adevice
, sizeof(adevice
), "%s", info
->printername
);
4264 if (info
->devmode
) {
4265 fstrcpy(info
->devmode
->devicename
, adevice
);
4268 if ( !(info
->data
= TALLOC_ZERO_P( info
, NT_PRINTER_DATA
)) ) {
4269 DEBUG(0,("unpack_values: talloc() failed!\n"));
4270 SAFE_FREE(dbuf
.dptr
);
4273 len
+= unpack_values( info
->data
, dbuf
.dptr
+len
, dbuf
.dsize
-len
);
4275 /* This will get the current RPC talloc context, but we should be
4276 passing this as a parameter... fixme... JRA ! */
4278 if (!nt_printing_getsec(info
, sharename
, &info
->secdesc_buf
)) {
4279 SAFE_FREE(dbuf
.dptr
);
4283 /* Fix for OS/2 drivers. */
4285 if (get_remote_arch() == RA_OS2
) {
4286 map_to_os2_driver(info
->drivername
);
4289 SAFE_FREE(dbuf
.dptr
);
4291 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4292 sharename
, info
->printername
, info
->drivername
));
4297 /****************************************************************************
4298 Debugging function, dump at level 6 the struct in the logs.
4299 ****************************************************************************/
4300 static uint32
dump_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4303 NT_PRINTER_INFO_LEVEL_2
*info2
;
4305 DEBUG(106,("Dumping printer at level [%d]\n", level
));
4310 if (printer
->info_2
== NULL
)
4314 info2
=printer
->info_2
;
4316 DEBUGADD(106,("attributes:[%d]\n", info2
->attributes
));
4317 DEBUGADD(106,("priority:[%d]\n", info2
->priority
));
4318 DEBUGADD(106,("default_priority:[%d]\n", info2
->default_priority
));
4319 DEBUGADD(106,("starttime:[%d]\n", info2
->starttime
));
4320 DEBUGADD(106,("untiltime:[%d]\n", info2
->untiltime
));
4321 DEBUGADD(106,("status:[%d]\n", info2
->status
));
4322 DEBUGADD(106,("cjobs:[%d]\n", info2
->cjobs
));
4323 DEBUGADD(106,("averageppm:[%d]\n", info2
->averageppm
));
4324 DEBUGADD(106,("changeid:[%d]\n", info2
->changeid
));
4325 DEBUGADD(106,("c_setprinter:[%d]\n", info2
->c_setprinter
));
4326 DEBUGADD(106,("setuptime:[%d]\n", info2
->setuptime
));
4328 DEBUGADD(106,("servername:[%s]\n", info2
->servername
));
4329 DEBUGADD(106,("printername:[%s]\n", info2
->printername
));
4330 DEBUGADD(106,("sharename:[%s]\n", info2
->sharename
));
4331 DEBUGADD(106,("portname:[%s]\n", info2
->portname
));
4332 DEBUGADD(106,("drivername:[%s]\n", info2
->drivername
));
4333 DEBUGADD(106,("comment:[%s]\n", info2
->comment
));
4334 DEBUGADD(106,("location:[%s]\n", info2
->location
));
4335 DEBUGADD(106,("sepfile:[%s]\n", info2
->sepfile
));
4336 DEBUGADD(106,("printprocessor:[%s]\n", info2
->printprocessor
));
4337 DEBUGADD(106,("datatype:[%s]\n", info2
->datatype
));
4338 DEBUGADD(106,("parameters:[%s]\n", info2
->parameters
));
4344 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level
));
4352 /****************************************************************************
4353 Update the changeid time.
4354 This is SO NASTY as some drivers need this to change, others need it
4355 static. This value will change every second, and I must hope that this
4356 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4358 ****************************************************************************/
4360 static uint32
rev_changeid(void)
4364 get_process_uptime(&tv
);
4367 /* Return changeid as msec since spooler restart */
4368 return tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000;
4371 * This setting seems to work well but is too untested
4372 * to replace the above calculation. Left in for experiementation
4373 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4375 return tv
.tv_sec
* 10 + tv
.tv_usec
/ 100000;
4381 * The function below are the high level ones.
4382 * only those ones must be called from the spoolss code.
4386 /****************************************************************************
4387 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4388 ****************************************************************************/
4390 WERROR
mod_a_printer(NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
4394 dump_a_printer(printer
, level
);
4400 * Update the changestamp. Emperical tests show that the
4401 * ChangeID is always updated,but c_setprinter is
4402 * global spooler variable (not per printer).
4405 /* ChangeID **must** be increasing over the lifetime
4406 of client's spoolss service in order for the
4407 client's cache to show updates */
4409 printer
->info_2
->changeid
= rev_changeid();
4412 * Because one day someone will ask:
4413 * NT->NT An admin connection to a remote
4414 * printer show changes imeediately in
4415 * the properities dialog
4417 * A non-admin connection will only show the
4418 * changes after viewing the properites page
4419 * 2 times. Seems to be related to a
4420 * race condition in the client between the spooler
4421 * updating the local cache and the Explorer.exe GUI
4422 * actually displaying the properties.
4424 * This is fixed in Win2k. admin/non-admin
4425 * connections both display changes immediately.
4430 result
=update_a_printer_2(printer
->info_2
);
4434 result
=WERR_UNKNOWN_LEVEL
;
4441 /****************************************************************************
4442 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4444 Previously the code had a memory allocation problem because it always
4445 used the TALLOC_CTX from the Printer_entry*. This context lasts
4446 as a long as the original handle is open. So if the client made a lot
4447 of getprinter[data]() calls, the memory usage would climb. Now we use
4448 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4449 still use the Printer_entry->ctx for maintaining the cache copy though
4450 since that object must live as long as the handle by definition.
4453 ****************************************************************************/
4455 static WERROR
get_a_printer_internal( Printer_entry
*print_hnd
, NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
,
4456 const char *sharename
, bool get_loc_com
)
4461 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
4463 if ( !(*pp_printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
4464 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4470 if ( !((*pp_printer
)->info_2
= TALLOC_ZERO_P(*pp_printer
, NT_PRINTER_INFO_LEVEL_2
)) ) {
4471 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4472 TALLOC_FREE( *pp_printer
);
4477 fstrcpy( servername
, print_hnd
->servername
);
4479 fstrcpy( servername
, "%L" );
4480 standard_sub_basic( "", "", servername
,
4481 sizeof(servername
)-1 );
4484 result
= get_a_printer_2( (*pp_printer
)->info_2
,
4485 servername
, sharename
, get_loc_com
);
4487 /* we have a new printer now. Save it with this handle */
4489 if ( !W_ERROR_IS_OK(result
) ) {
4490 TALLOC_FREE( *pp_printer
);
4491 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4492 sharename
, (unsigned int)level
, win_errstr(result
)));
4496 dump_a_printer( *pp_printer
, level
);
4501 TALLOC_FREE( *pp_printer
);
4502 return WERR_UNKNOWN_LEVEL
;
4508 WERROR
get_a_printer( Printer_entry
*print_hnd
,
4509 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4511 const char *sharename
)
4513 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4517 WERROR
get_a_printer_search( Printer_entry
*print_hnd
,
4518 NT_PRINTER_INFO_LEVEL
**pp_printer
,
4520 const char *sharename
)
4522 return get_a_printer_internal(print_hnd
, pp_printer
, level
,
4526 /****************************************************************************
4527 Deletes a NT_PRINTER_INFO_LEVEL struct.
4528 ****************************************************************************/
4530 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
4532 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
4539 if ( printer
->info_2
)
4540 free_nt_printer_info_level_2(&printer
->info_2
);
4544 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level
));
4548 TALLOC_FREE(*pp_printer
);
4553 /****************************************************************************
4554 ****************************************************************************/
4556 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr
*r
,
4557 struct spoolss_DriverInfo8
*_info8
)
4559 struct spoolss_DriverInfo8 info8
;
4565 info8
.version
= r
->info
.info3
->version
;
4566 info8
.driver_name
= r
->info
.info3
->driver_name
;
4567 info8
.architecture
= r
->info
.info3
->architecture
;
4568 info8
.driver_path
= r
->info
.info3
->driver_path
;
4569 info8
.data_file
= r
->info
.info3
->data_file
;
4570 info8
.config_file
= r
->info
.info3
->config_file
;
4571 info8
.help_file
= r
->info
.info3
->help_file
;
4572 info8
.monitor_name
= r
->info
.info3
->monitor_name
;
4573 info8
.default_datatype
= r
->info
.info3
->default_datatype
;
4574 if (r
->info
.info3
->dependent_files
&& r
->info
.info3
->dependent_files
->string
) {
4575 info8
.dependent_files
= r
->info
.info3
->dependent_files
->string
;
4579 info8
.version
= r
->info
.info6
->version
;
4580 info8
.driver_name
= r
->info
.info6
->driver_name
;
4581 info8
.architecture
= r
->info
.info6
->architecture
;
4582 info8
.driver_path
= r
->info
.info6
->driver_path
;
4583 info8
.data_file
= r
->info
.info6
->data_file
;
4584 info8
.config_file
= r
->info
.info6
->config_file
;
4585 info8
.help_file
= r
->info
.info6
->help_file
;
4586 info8
.monitor_name
= r
->info
.info6
->monitor_name
;
4587 info8
.default_datatype
= r
->info
.info6
->default_datatype
;
4588 if (r
->info
.info6
->dependent_files
&& r
->info
.info6
->dependent_files
->string
) {
4589 info8
.dependent_files
= r
->info
.info6
->dependent_files
->string
;
4591 info8
.driver_date
= r
->info
.info6
->driver_date
;
4592 info8
.driver_version
= r
->info
.info6
->driver_version
;
4593 info8
.manufacturer_name
= r
->info
.info6
->manufacturer_name
;
4594 info8
.manufacturer_url
= r
->info
.info6
->manufacturer_url
;
4595 info8
.hardware_id
= r
->info
.info6
->hardware_id
;
4596 info8
.provider
= r
->info
.info6
->provider
;
4599 info8
.version
= r
->info
.info8
->version
;
4600 info8
.driver_name
= r
->info
.info8
->driver_name
;
4601 info8
.architecture
= r
->info
.info8
->architecture
;
4602 info8
.driver_path
= r
->info
.info8
->driver_path
;
4603 info8
.data_file
= r
->info
.info8
->data_file
;
4604 info8
.config_file
= r
->info
.info8
->config_file
;
4605 info8
.help_file
= r
->info
.info8
->help_file
;
4606 info8
.monitor_name
= r
->info
.info8
->monitor_name
;
4607 info8
.default_datatype
= r
->info
.info8
->default_datatype
;
4608 if (r
->info
.info8
->dependent_files
&& r
->info
.info8
->dependent_files
->string
) {
4609 info8
.dependent_files
= r
->info
.info8
->dependent_files
->string
;
4611 if (r
->info
.info8
->previous_names
&& r
->info
.info8
->previous_names
->string
) {
4612 info8
.previous_names
= r
->info
.info8
->previous_names
->string
;
4614 info8
.driver_date
= r
->info
.info8
->driver_date
;
4615 info8
.driver_version
= r
->info
.info8
->driver_version
;
4616 info8
.manufacturer_name
= r
->info
.info8
->manufacturer_name
;
4617 info8
.manufacturer_url
= r
->info
.info8
->manufacturer_url
;
4618 info8
.hardware_id
= r
->info
.info8
->hardware_id
;
4619 info8
.provider
= r
->info
.info8
->provider
;
4620 info8
.print_processor
= r
->info
.info8
->print_processor
;
4621 info8
.vendor_setup
= r
->info
.info8
->vendor_setup
;
4622 if (r
->info
.info8
->color_profiles
&& r
->info
.info8
->color_profiles
->string
) {
4623 info8
.color_profiles
= r
->info
.info8
->color_profiles
->string
;
4625 info8
.inf_path
= r
->info
.info8
->inf_path
;
4626 info8
.printer_driver_attributes
= r
->info
.info8
->printer_driver_attributes
;
4627 if (r
->info
.info8
->core_driver_dependencies
&& r
->info
.info8
->core_driver_dependencies
->string
) {
4628 info8
.core_driver_dependencies
= r
->info
.info8
->core_driver_dependencies
->string
;
4630 info8
.min_inbox_driver_ver_date
= r
->info
.info8
->min_inbox_driver_ver_date
;
4631 info8
.min_inbox_driver_ver_version
= r
->info
.info8
->min_inbox_driver_ver_version
;
4643 uint32_t add_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4644 struct spoolss_AddDriverInfoCtr
*r
,
4648 struct spoolss_DriverInfo8 info8
;
4652 DEBUG(10,("adding a printer at level [%d]\n", r
->level
));
4654 if (!driver_info_ctr_to_info8(r
, &info8
)) {
4658 *driver_name
= talloc_strdup(mem_ctx
, info8
.driver_name
);
4659 if (!*driver_name
) {
4662 *version
= info8
.version
;
4664 return add_a_printer_driver_8(&info8
);
4667 /****************************************************************************
4668 ****************************************************************************/
4670 WERROR
get_a_printer_driver(TALLOC_CTX
*mem_ctx
,
4671 struct spoolss_DriverInfo8
**driver
,
4672 const char *drivername
, const char *architecture
,
4676 struct spoolss_DriverInfo3 info3
;
4677 struct spoolss_DriverInfo8
*info8
;
4681 /* Sometime we just want any version of the driver */
4683 if (version
== DRIVER_ANY_VERSION
) {
4684 /* look for Win2k first and then for NT4 */
4685 result
= get_a_printer_driver_3(mem_ctx
,
4689 if (!W_ERROR_IS_OK(result
)) {
4690 result
= get_a_printer_driver_3(mem_ctx
,
4696 result
= get_a_printer_driver_3(mem_ctx
,
4703 if (!W_ERROR_IS_OK(result
)) {
4707 info8
= talloc_zero(mem_ctx
, struct spoolss_DriverInfo8
);
4712 info8
->version
= info3
.version
;
4713 info8
->driver_name
= info3
.driver_name
;
4714 info8
->architecture
= info3
.architecture
;
4715 info8
->driver_path
= info3
.driver_path
;
4716 info8
->data_file
= info3
.data_file
;
4717 info8
->config_file
= info3
.config_file
;
4718 info8
->help_file
= info3
.help_file
;
4719 info8
->dependent_files
= info3
.dependent_files
;
4720 info8
->monitor_name
= info3
.monitor_name
;
4721 info8
->default_datatype
= info3
.default_datatype
;
4728 /****************************************************************************
4729 ****************************************************************************/
4731 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8
*driver
)
4733 talloc_free(driver
);
4738 /****************************************************************************
4739 Determine whether or not a particular driver is currently assigned
4741 ****************************************************************************/
4743 bool printer_driver_in_use(const struct spoolss_DriverInfo8
*r
)
4746 int n_services
= lp_numservices();
4747 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4748 bool in_use
= False
;
4754 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4756 /* loop through the printers.tdb and check for the drivername */
4758 for (snum
=0; snum
<n_services
&& !in_use
; snum
++) {
4759 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
4762 if ( !W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_servicename(snum
))) )
4765 if (strequal(r
->driver_name
, printer
->info_2
->drivername
))
4768 free_a_printer( &printer
, 2 );
4771 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4774 struct spoolss_DriverInfo8
*d
;
4777 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r
->driver_name
));
4779 /* we can still remove the driver if there is one of
4780 "Windows NT x86" version 2 or 3 left */
4782 if (!strequal("Windows NT x86", r
->architecture
)) {
4783 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", DRIVER_ANY_VERSION
);
4786 switch (r
->version
) {
4788 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 3);
4791 werr
= get_a_printer_driver(talloc_tos(), &d
, r
->driver_name
, "Windows NT x86", 2);
4794 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4796 werr
= WERR_UNKNOWN_PRINTER_DRIVER
;
4801 /* now check the error code */
4803 if ( W_ERROR_IS_OK(werr
) ) {
4804 /* it's ok to remove the driver, we have other architctures left */
4806 free_a_printer_driver(d
);
4810 /* report that the driver is not in use by default */
4816 /**********************************************************************
4817 Check to see if a ogiven file is in use by *info
4818 *********************************************************************/
4820 static bool drv_file_in_use(const char *file
, const struct spoolss_DriverInfo8
*info
)
4827 /* mz: skip files that are in the list but already deleted */
4828 if (!file
|| !file
[0]) {
4832 if (strequal(file
, info
->driver_path
))
4835 if (strequal(file
, info
->data_file
))
4838 if (strequal(file
, info
->config_file
))
4841 if (strequal(file
, info
->help_file
))
4844 /* see of there are any dependent files to examine */
4846 if (!info
->dependent_files
)
4849 while (info
->dependent_files
[i
] && *info
->dependent_files
[i
]) {
4850 if (strequal(file
, info
->dependent_files
[i
]))
4859 /**********************************************************************
4860 Utility function to remove the dependent file pointed to by the
4861 input parameter from the list
4862 *********************************************************************/
4864 static void trim_dependent_file(TALLOC_CTX
*mem_ctx
, const char **files
, int idx
)
4867 /* bump everything down a slot */
4869 while (files
&& files
[idx
+1]) {
4870 files
[idx
] = talloc_strdup(mem_ctx
, files
[idx
+1]);
4879 /**********************************************************************
4880 Check if any of the files used by src are also used by drv
4881 *********************************************************************/
4883 static bool trim_overlap_drv_files(TALLOC_CTX
*mem_ctx
,
4884 struct spoolss_DriverInfo8
*src
,
4885 const struct spoolss_DriverInfo8
*drv
)
4887 bool in_use
= False
;
4893 /* check each file. Remove it from the src structure if it overlaps */
4895 if (drv_file_in_use(src
->driver_path
, drv
)) {
4897 DEBUG(10,("Removing driverfile [%s] from list\n", src
->driver_path
));
4898 src
->driver_path
= talloc_strdup(mem_ctx
, "");
4899 if (!src
->driver_path
) { return false; }
4902 if (drv_file_in_use(src
->data_file
, drv
)) {
4904 DEBUG(10,("Removing datafile [%s] from list\n", src
->data_file
));
4905 src
->data_file
= talloc_strdup(mem_ctx
, "");
4906 if (!src
->data_file
) { return false; }
4909 if (drv_file_in_use(src
->config_file
, drv
)) {
4911 DEBUG(10,("Removing configfile [%s] from list\n", src
->config_file
));
4912 src
->config_file
= talloc_strdup(mem_ctx
, "");
4913 if (!src
->config_file
) { return false; }
4916 if (drv_file_in_use(src
->help_file
, drv
)) {
4918 DEBUG(10,("Removing helpfile [%s] from list\n", src
->help_file
));
4919 src
->help_file
= talloc_strdup(mem_ctx
, "");
4920 if (!src
->help_file
) { return false; }
4923 /* are there any dependentfiles to examine? */
4925 if (!src
->dependent_files
)
4928 while (src
->dependent_files
[i
] && *src
->dependent_files
[i
]) {
4929 if (drv_file_in_use(src
->dependent_files
[i
], drv
)) {
4931 DEBUG(10,("Removing [%s] from dependent file list\n", src
->dependent_files
[i
]));
4932 trim_dependent_file(mem_ctx
, src
->dependent_files
, i
);
4940 /****************************************************************************
4941 Determine whether or not a particular driver files are currently being
4942 used by any other driver.
4944 Return value is True if any files were in use by other drivers
4945 and False otherwise.
4947 Upon return, *info has been modified to only contain the driver files
4948 which are not in use
4952 This needs to check all drivers to ensure that all files in use
4953 have been removed from *info, not just the ones in the first
4955 ****************************************************************************/
4957 bool printer_driver_files_in_use(TALLOC_CTX
*mem_ctx
,
4958 struct spoolss_DriverInfo8
*info
)
4963 fstring
*list
= NULL
;
4964 struct spoolss_DriverInfo8
*driver
;
4965 bool in_use
= false;
4970 version
= info
->version
;
4972 /* loop over all driver versions */
4974 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4976 /* get the list of drivers */
4979 ndrivers
= get_ntdrivers(&list
, info
->architecture
, version
);
4981 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4982 ndrivers
, info
->architecture
, version
));
4984 /* check each driver for overlap in files */
4986 for (i
=0; i
<ndrivers
; i
++) {
4987 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4991 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, list
[i
], info
->architecture
, version
))) {
4996 /* check if d2 uses any files from d1 */
4997 /* only if this is a different driver than the one being deleted */
4999 if (!strequal(info
->driver_name
, driver
->driver_name
)) {
5000 if (trim_overlap_drv_files(mem_ctx
, info
, driver
)) {
5001 /* mz: Do not instantly return -
5002 * we need to ensure this file isn't
5003 * also in use by other drivers. */
5008 free_a_printer_driver(driver
);
5013 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5018 static NTSTATUS
driver_unlink_internals(connection_struct
*conn
,
5021 struct smb_filename
*smb_fname
= NULL
;
5024 status
= create_synthetic_smb_fname(talloc_tos(), name
, NULL
, NULL
,
5026 if (!NT_STATUS_IS_OK(status
)) {
5030 status
= unlink_internals(conn
, NULL
, 0, smb_fname
, false);
5032 TALLOC_FREE(smb_fname
);
5036 /****************************************************************************
5037 Actually delete the driver files. Make sure that
5038 printer_driver_files_in_use() return False before calling
5040 ****************************************************************************/
5042 static bool delete_driver_files(struct pipes_struct
*rpc_pipe
,
5043 const struct spoolss_DriverInfo8
*r
)
5048 connection_struct
*conn
;
5051 fstring printdollar
;
5052 int printdollar_snum
;
5059 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5060 r
->driver_name
, r
->version
));
5062 fstrcpy(printdollar
, "print$");
5064 printdollar_snum
= find_service(printdollar
);
5065 if (printdollar_snum
== -1) {
5069 nt_status
= create_conn_struct(talloc_tos(), &conn
, printdollar_snum
,
5070 lp_pathname(printdollar_snum
),
5071 rpc_pipe
->server_info
, &oldcwd
);
5072 if (!NT_STATUS_IS_OK(nt_status
)) {
5073 DEBUG(0,("delete_driver_files: create_conn_struct "
5074 "returned %s\n", nt_errstr(nt_status
)));
5078 if ( !CAN_WRITE(conn
) ) {
5079 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5083 /* now delete the files; must strip the '\print$' string from
5086 if (r
->driver_path
&& r
->driver_path
[0]) {
5087 if ((s
= strchr(&r
->driver_path
[1], '\\')) != NULL
) {
5089 DEBUG(10,("deleting driverfile [%s]\n", s
));
5090 driver_unlink_internals(conn
, file
);
5094 if (r
->config_file
&& r
->config_file
[0]) {
5095 if ((s
= strchr(&r
->config_file
[1], '\\')) != NULL
) {
5097 DEBUG(10,("deleting configfile [%s]\n", s
));
5098 driver_unlink_internals(conn
, file
);
5102 if (r
->data_file
&& r
->data_file
[0]) {
5103 if ((s
= strchr(&r
->data_file
[1], '\\')) != NULL
) {
5105 DEBUG(10,("deleting datafile [%s]\n", s
));
5106 driver_unlink_internals(conn
, file
);
5110 if (r
->help_file
&& r
->help_file
[0]) {
5111 if ((s
= strchr(&r
->help_file
[1], '\\')) != NULL
) {
5113 DEBUG(10,("deleting helpfile [%s]\n", s
));
5114 driver_unlink_internals(conn
, file
);
5118 /* check if we are done removing files */
5120 if (r
->dependent_files
) {
5121 while (r
->dependent_files
[i
] && r
->dependent_files
[i
][0]) {
5124 /* bypass the "\print$" portion of the path */
5126 if ((p
= strchr(r
->dependent_files
[i
]+1, '\\')) != NULL
) {
5128 DEBUG(10,("deleting dependent file [%s]\n", file
));
5129 driver_unlink_internals(conn
, file
);
5141 vfs_ChDir(conn
, oldcwd
);
5147 /****************************************************************************
5148 Remove a printer driver from the TDB. This assumes that the the driver was
5149 previously looked up.
5150 ***************************************************************************/
5152 WERROR
delete_printer_driver(struct pipes_struct
*rpc_pipe
,
5153 const struct spoolss_DriverInfo8
*r
,
5154 uint32 version
, bool delete_files
)
5160 /* delete the tdb data first */
5162 arch
= get_short_archi(r
->architecture
);
5164 return WERR_UNKNOWN_PRINTER_DRIVER
;
5166 if (asprintf(&key
, "%s%s/%d/%s", DRIVERS_PREFIX
,
5167 arch
, version
, r
->driver_name
) < 0) {
5171 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5172 key
, delete_files
? "TRUE" : "FALSE" ));
5174 /* check if the driver actually exists for this environment */
5176 dbuf
= tdb_fetch_bystring( tdb_drivers
, key
);
5178 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key
));
5180 return WERR_UNKNOWN_PRINTER_DRIVER
;
5183 SAFE_FREE( dbuf
.dptr
);
5185 /* ok... the driver exists so the delete should return success */
5187 if (tdb_delete_bystring(tdb_drivers
, key
) == -1) {
5188 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key
));
5190 return WERR_ACCESS_DENIED
;
5194 * now delete any associated files if delete_files == True
5195 * even if this part failes, we return succes because the
5196 * driver doesn not exist any more
5200 delete_driver_files(rpc_pipe
, r
);
5202 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key
));
5208 /****************************************************************************
5209 Store a security desc for a printer.
5210 ****************************************************************************/
5212 WERROR
nt_printing_setsec(const char *sharename
, struct sec_desc_buf
*secdesc_ctr
)
5214 struct sec_desc_buf
*new_secdesc_ctr
= NULL
;
5215 struct sec_desc_buf
*old_secdesc_ctr
= NULL
;
5216 TALLOC_CTX
*mem_ctx
= NULL
;
5223 mem_ctx
= talloc_init("nt_printing_setsec");
5224 if (mem_ctx
== NULL
)
5227 /* The old owner and group sids of the security descriptor are not
5228 present when new ACEs are added or removed by changing printer
5229 permissions through NT. If they are NULL in the new security
5230 descriptor then copy them over from the old one. */
5232 if (!secdesc_ctr
->sd
->owner_sid
|| !secdesc_ctr
->sd
->group_sid
) {
5233 struct dom_sid
*owner_sid
, *group_sid
;
5234 struct security_acl
*dacl
, *sacl
;
5235 struct security_descriptor
*psd
= NULL
;
5238 if (!nt_printing_getsec(mem_ctx
, sharename
, &old_secdesc_ctr
)) {
5239 status
= WERR_NOMEM
;
5243 /* Pick out correct owner and group sids */
5245 owner_sid
= secdesc_ctr
->sd
->owner_sid
?
5246 secdesc_ctr
->sd
->owner_sid
:
5247 old_secdesc_ctr
->sd
->owner_sid
;
5249 group_sid
= secdesc_ctr
->sd
->group_sid
?
5250 secdesc_ctr
->sd
->group_sid
:
5251 old_secdesc_ctr
->sd
->group_sid
;
5253 dacl
= secdesc_ctr
->sd
->dacl
?
5254 secdesc_ctr
->sd
->dacl
:
5255 old_secdesc_ctr
->sd
->dacl
;
5257 sacl
= secdesc_ctr
->sd
->sacl
?
5258 secdesc_ctr
->sd
->sacl
:
5259 old_secdesc_ctr
->sd
->sacl
;
5261 /* Make a deep copy of the security descriptor */
5263 psd
= make_sec_desc(mem_ctx
, secdesc_ctr
->sd
->revision
, secdesc_ctr
->sd
->type
,
5264 owner_sid
, group_sid
,
5270 status
= WERR_NOMEM
;
5274 new_secdesc_ctr
= make_sec_desc_buf(mem_ctx
, size
, psd
);
5277 if (!new_secdesc_ctr
) {
5278 new_secdesc_ctr
= secdesc_ctr
;
5281 /* Store the security descriptor in a tdb */
5283 nt_status
= marshall_sec_desc_buf(mem_ctx
, new_secdesc_ctr
,
5284 &blob
.data
, &blob
.length
);
5285 if (!NT_STATUS_IS_OK(nt_status
)) {
5286 status
= ntstatus_to_werror(nt_status
);
5290 kbuf
= make_printers_secdesc_tdbkey(mem_ctx
, sharename
);
5292 dbuf
.dptr
= (unsigned char *)blob
.data
;
5293 dbuf
.dsize
= blob
.length
;
5295 if (tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
)==0) {
5298 DEBUG(1,("Failed to store secdesc for %s\n", sharename
));
5299 status
= WERR_BADFUNC
;
5302 /* Free malloc'ed memory */
5303 talloc_free(blob
.data
);
5308 talloc_destroy(mem_ctx
);
5312 /****************************************************************************
5313 Construct a default security descriptor buffer for a printer.
5314 ****************************************************************************/
5316 static struct sec_desc_buf
*construct_default_printer_sdb(TALLOC_CTX
*ctx
)
5318 struct security_ace ace
[5]; /* max number of ace entries */
5321 struct security_acl
*psa
= NULL
;
5322 struct sec_desc_buf
*sdb
= NULL
;
5323 struct security_descriptor
*psd
= NULL
;
5324 struct dom_sid adm_sid
;
5327 /* Create an ACE where Everyone is allowed to print */
5329 sa
= PRINTER_ACE_PRINT
;
5330 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5331 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5333 /* Add the domain admins group if we are a DC */
5336 struct dom_sid domadmins_sid
;
5338 sid_compose(&domadmins_sid
, get_global_sam_sid(),
5341 sa
= PRINTER_ACE_FULL_CONTROL
;
5342 init_sec_ace(&ace
[i
++], &domadmins_sid
,
5343 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5344 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5345 init_sec_ace(&ace
[i
++], &domadmins_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5346 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5348 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid
)) {
5349 sid_append_rid(&adm_sid
, DOMAIN_RID_ADMINISTRATOR
);
5351 sa
= PRINTER_ACE_FULL_CONTROL
;
5352 init_sec_ace(&ace
[i
++], &adm_sid
,
5353 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5354 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5355 init_sec_ace(&ace
[i
++], &adm_sid
, SEC_ACE_TYPE_ACCESS_ALLOWED
,
5356 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5359 /* add BUILTIN\Administrators as FULL CONTROL */
5361 sa
= PRINTER_ACE_FULL_CONTROL
;
5362 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5363 SEC_ACE_TYPE_ACCESS_ALLOWED
, sa
,
5364 SEC_ACE_FLAG_OBJECT_INHERIT
| SEC_ACE_FLAG_INHERIT_ONLY
);
5365 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
5366 SEC_ACE_TYPE_ACCESS_ALLOWED
,
5367 sa
, SEC_ACE_FLAG_CONTAINER_INHERIT
);
5369 /* Make the security descriptor owned by the BUILTIN\Administrators */
5371 /* The ACL revision number in rpc_secdesc.h differs from the one
5372 created by NT when setting ACE entries in printer
5373 descriptors. NT4 complains about the property being edited by a
5376 if ((psa
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) != NULL
) {
5377 psd
= make_sec_desc(ctx
, SD_REVISION
, SEC_DESC_SELF_RELATIVE
,
5378 &global_sid_Builtin_Administrators
,
5379 &global_sid_Builtin_Administrators
,
5380 NULL
, psa
, &sd_size
);
5384 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5388 sdb
= make_sec_desc_buf(ctx
, sd_size
, psd
);
5390 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5391 (unsigned int)sd_size
));
5396 /****************************************************************************
5397 Get a security desc for a printer.
5398 ****************************************************************************/
5400 bool nt_printing_getsec(TALLOC_CTX
*ctx
, const char *sharename
, struct sec_desc_buf
**secdesc_ctr
)
5408 if (strlen(sharename
) > 2 && (temp
= strchr(sharename
+ 2, '\\'))) {
5409 sharename
= temp
+ 1;
5412 /* Fetch security descriptor from tdb */
5414 kbuf
= make_printers_secdesc_tdbkey(ctx
, sharename
);
5416 dbuf
= tdb_fetch(tdb_printers
, kbuf
);
5419 status
= unmarshall_sec_desc_buf(ctx
, dbuf
.dptr
, dbuf
.dsize
,
5421 SAFE_FREE(dbuf
.dptr
);
5423 if (NT_STATUS_IS_OK(status
)) {
5428 *secdesc_ctr
= construct_default_printer_sdb(ctx
);
5429 if (!*secdesc_ctr
) {
5433 status
= marshall_sec_desc_buf(ctx
, *secdesc_ctr
,
5434 &blob
.data
, &blob
.length
);
5435 if (NT_STATUS_IS_OK(status
)) {
5436 dbuf
.dptr
= (unsigned char *)blob
.data
;
5437 dbuf
.dsize
= blob
.length
;
5438 tdb_trans_store(tdb_printers
, kbuf
, dbuf
, TDB_REPLACE
);
5439 talloc_free(blob
.data
);
5442 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5443 this security descriptor has been created when winbindd was
5444 down. Take ownership of security descriptor. */
5446 if (sid_equal((*secdesc_ctr
)->sd
->owner_sid
, &global_sid_World
)) {
5447 struct dom_sid owner_sid
;
5449 /* Change sd owner to workgroup administrator */
5451 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid
)) {
5452 struct sec_desc_buf
*new_secdesc_ctr
= NULL
;
5453 struct security_descriptor
*psd
= NULL
;
5458 sid_append_rid(&owner_sid
, DOMAIN_RID_ADMINISTRATOR
);
5460 psd
= make_sec_desc(ctx
, (*secdesc_ctr
)->sd
->revision
, (*secdesc_ctr
)->sd
->type
,
5462 (*secdesc_ctr
)->sd
->group_sid
,
5463 (*secdesc_ctr
)->sd
->sacl
,
5464 (*secdesc_ctr
)->sd
->dacl
,
5471 new_secdesc_ctr
= make_sec_desc_buf(ctx
, size
, psd
);
5472 if (!new_secdesc_ctr
) {
5476 /* Swap with other one */
5478 *secdesc_ctr
= new_secdesc_ctr
;
5482 nt_printing_setsec(sharename
, *secdesc_ctr
);
5486 if (DEBUGLEVEL
>= 10) {
5487 struct security_acl
*the_acl
= (*secdesc_ctr
)->sd
->dacl
;
5490 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5491 sharename
, the_acl
->num_aces
));
5493 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5494 DEBUG(10, ("%s %d %d 0x%08x\n",
5495 sid_string_dbg(&the_acl
->aces
[i
].trustee
),
5496 the_acl
->aces
[i
].type
, the_acl
->aces
[i
].flags
,
5497 the_acl
->aces
[i
].access_mask
));
5506 1: level not implemented
5507 2: file doesn't exist
5508 3: can't allocate memory
5509 4: can't free memory
5510 5: non existant struct
5514 A printer and a printer driver are 2 different things.
5515 NT manages them separatelly, Samba does the same.
5516 Why ? Simply because it's easier and it makes sense !
5518 Now explanation: You have 3 printers behind your samba server,
5519 2 of them are the same make and model (laser A and B). But laser B
5520 has an 3000 sheet feeder and laser A doesn't such an option.
5521 Your third printer is an old dot-matrix model for the accounting :-).
5523 If the /usr/local/samba/lib directory (default dir), you will have
5524 5 files to describe all of this.
5526 3 files for the printers (1 by printer):
5529 NTprinter_accounting
5530 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5531 NTdriver_printer model X
5532 NTdriver_printer model Y
5534 jfm: I should use this comment for the text file to explain
5535 same thing for the forms BTW.
5536 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5540 /* Convert generic access rights to printer object specific access rights.
5541 It turns out that NT4 security descriptors use generic access rights and
5542 NT5 the object specific ones. */
5544 void map_printer_permissions(struct security_descriptor
*sd
)
5548 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5549 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5550 &printer_generic_mapping
);
5554 void map_job_permissions(struct security_descriptor
*sd
)
5558 for (i
= 0; sd
->dacl
&& i
< sd
->dacl
->num_aces
; i
++) {
5559 se_map_generic(&sd
->dacl
->aces
[i
].access_mask
,
5560 &job_generic_mapping
);
5565 /****************************************************************************
5566 Check a user has permissions to perform the given operation. We use the
5567 permission constants defined in include/rpc_spoolss.h to check the various
5568 actions we perform when checking printer access.
5570 PRINTER_ACCESS_ADMINISTER:
5571 print_queue_pause, print_queue_resume, update_printer_sec,
5572 update_printer, spoolss_addprinterex_level_2,
5573 _spoolss_setprinterdata
5578 JOB_ACCESS_ADMINISTER:
5579 print_job_delete, print_job_pause, print_job_resume,
5582 Try access control in the following order (for performance reasons):
5583 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5584 2) check security descriptor (bit comparisons in memory)
5585 3) "printer admins" (may result in numerous calls to winbind)
5587 ****************************************************************************/
5588 bool print_access_check(struct auth_serversupplied_info
*server_info
, int snum
,
5591 struct sec_desc_buf
*secdesc
= NULL
;
5592 uint32 access_granted
;
5595 TALLOC_CTX
*mem_ctx
= NULL
;
5596 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5598 /* If user is NULL then use the current_user structure */
5600 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5602 if (server_info
->utok
.uid
== sec_initial_uid()
5603 || user_has_privileges(server_info
->ptok
, &se_printop
) ) {
5607 /* Get printer name */
5609 pname
= PRINTERNAME(snum
);
5611 if (!pname
|| !*pname
) {
5616 /* Get printer security descriptor */
5618 if(!(mem_ctx
= talloc_init("print_access_check"))) {
5623 if (!nt_printing_getsec(mem_ctx
, pname
, &secdesc
)) {
5624 talloc_destroy(mem_ctx
);
5629 if (access_type
== JOB_ACCESS_ADMINISTER
) {
5630 struct sec_desc_buf
*parent_secdesc
= secdesc
;
5632 /* Create a child security descriptor to check permissions
5633 against. This is because print jobs are child objects
5634 objects of a printer. */
5636 status
= se_create_child_secdesc_buf(mem_ctx
, &secdesc
, parent_secdesc
->sd
, False
);
5638 if (!NT_STATUS_IS_OK(status
)) {
5639 talloc_destroy(mem_ctx
);
5640 errno
= map_errno_from_nt_status(status
);
5644 map_job_permissions(secdesc
->sd
);
5646 map_printer_permissions(secdesc
->sd
);
5650 status
= se_access_check(secdesc
->sd
, server_info
->ptok
, access_type
,
5653 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status
) ? "SUCCESS" : "FAILURE"));
5655 /* see if we need to try the printer admin list */
5657 if (!NT_STATUS_IS_OK(status
) &&
5658 (token_contains_name_in_list(uidtoname(server_info
->utok
.uid
),
5659 NULL
, NULL
, server_info
->ptok
,
5660 lp_printer_admin(snum
)))) {
5661 talloc_destroy(mem_ctx
);
5665 talloc_destroy(mem_ctx
);
5667 if (!NT_STATUS_IS_OK(status
)) {
5671 return NT_STATUS_IS_OK(status
);
5674 /****************************************************************************
5675 Check the time parameters allow a print operation.
5676 *****************************************************************************/
5678 bool print_time_access_check(const char *servicename
)
5680 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5682 time_t now
= time(NULL
);
5686 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
5689 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
5693 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
5695 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
5698 free_a_printer(&printer
, 2);
5706 /****************************************************************************
5707 Fill in the servername sent in the _spoolss_open_printer_ex() call
5708 ****************************************************************************/
5710 char* get_server_name( Printer_entry
*printer
)
5712 return printer
->servername
;