try to generate file version
[Samba/ekacnet.git] / source3 / printing / nt_printing.c
blob916de2578f2ad4b13cbe130596cda239c84401d0
1 /*
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/>.
22 #include "includes.h"
24 static TDB_CONTEXT *tdb_forms; /* used for forms files */
25 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
26 static TDB_CONTEXT *tdb_printers; /* used for printers files */
28 #define FORMS_PREFIX "FORMS/"
29 #define DRIVERS_PREFIX "DRIVERS/"
30 #define DRIVERS_PREFIX8 "DRIVERS8/"
31 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
32 #define PRINTERS_PREFIX "PRINTERS/"
33 #define SECDESC_PREFIX "SECDESC/"
34 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
36 #define NTDRIVERS_DATABASE_VERSION_1 1
37 #define NTDRIVERS_DATABASE_VERSION_2 2
38 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
39 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
40 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
42 /* Map generic permissions to printer object specific permissions */
44 const struct generic_mapping printer_generic_mapping = {
45 PRINTER_READ,
46 PRINTER_WRITE,
47 PRINTER_EXECUTE,
48 PRINTER_ALL_ACCESS
51 const struct standard_mapping printer_std_mapping = {
52 PRINTER_READ,
53 PRINTER_WRITE,
54 PRINTER_EXECUTE,
55 PRINTER_ALL_ACCESS
58 /* Map generic permissions to print server object specific permissions */
60 const struct generic_mapping printserver_generic_mapping = {
61 SERVER_READ,
62 SERVER_WRITE,
63 SERVER_EXECUTE,
64 SERVER_ALL_ACCESS
67 const struct generic_mapping printserver_std_mapping = {
68 SERVER_READ,
69 SERVER_WRITE,
70 SERVER_EXECUTE,
71 SERVER_ALL_ACCESS
74 /* Map generic permissions to job object specific permissions */
76 const struct generic_mapping job_generic_mapping = {
77 JOB_READ,
78 JOB_WRITE,
79 JOB_EXECUTE,
80 JOB_ALL_ACCESS
83 /* We need one default form to support our default printer. Msoft adds the
84 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
85 array index). Letter is always first, so (for the current code) additions
86 always put things in the correct order. */
87 static const nt_forms_struct default_forms[] = {
88 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
89 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
91 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
92 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
93 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
94 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
95 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
96 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
97 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
99 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
100 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
101 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
102 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
103 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
104 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
105 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
106 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
107 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
108 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
109 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
110 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
111 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
112 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
113 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
114 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
115 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
116 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
117 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
118 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
119 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
120 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
121 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
122 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
123 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
124 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
125 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
126 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
127 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
128 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
129 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
130 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
131 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
132 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
133 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
134 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
135 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
136 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
138 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
139 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
140 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
141 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
142 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
143 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
144 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
145 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
146 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
147 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
148 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
149 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
150 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
151 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
152 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
153 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
154 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
155 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
156 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
157 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
158 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
159 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
160 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
161 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
162 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
163 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
164 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
165 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
166 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
167 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
168 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
169 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
170 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
171 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
172 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
173 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
174 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
175 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
176 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
177 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
178 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
179 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
180 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
181 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
182 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
183 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
184 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
185 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
186 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
187 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
188 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
189 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
190 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
191 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
192 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
193 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
194 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
195 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
196 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
197 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
198 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
199 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
200 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
201 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
202 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
203 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
204 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
205 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
208 static const struct print_architecture_table_node archi_table[]= {
210 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
211 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
212 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
213 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
214 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
215 {"Windows IA64", SPL_ARCH_IA64, 3 },
216 {"Windows x64", SPL_ARCH_X64, 3 },
217 {NULL, "", -1 }
221 /****************************************************************************
222 generate a new TDB_DATA key for storing a printer
223 ****************************************************************************/
225 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
227 fstring share;
228 char *keystr = NULL;
229 TDB_DATA key;
231 fstrcpy(share, sharename);
232 strlower_m(share);
234 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
235 key = string_term_tdb_data(keystr ? keystr : "");
237 return key;
240 /****************************************************************************
241 generate a new TDB_DATA key for storing a printer security descriptor
242 ****************************************************************************/
244 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
245 const char* sharename )
247 fstring share;
248 char *keystr = NULL;
249 TDB_DATA key;
251 fstrcpy(share, sharename );
252 strlower_m(share);
254 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
255 key = string_term_tdb_data(keystr ? keystr : "");
257 return key;
260 /****************************************************************************
261 ****************************************************************************/
263 static bool upgrade_to_version_3(void)
265 TDB_DATA kbuf, newkey, dbuf;
267 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
269 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
270 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
272 dbuf = tdb_fetch(tdb_drivers, kbuf);
274 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
275 DEBUG(0,("upgrade_to_version_3:moving form\n"));
276 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
277 SAFE_FREE(dbuf.dptr);
278 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
279 return False;
281 if (tdb_delete(tdb_drivers, kbuf) != 0) {
282 SAFE_FREE(dbuf.dptr);
283 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
284 return False;
288 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
289 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
290 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
291 SAFE_FREE(dbuf.dptr);
292 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
293 return False;
295 if (tdb_delete(tdb_drivers, kbuf) != 0) {
296 SAFE_FREE(dbuf.dptr);
297 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
298 return False;
302 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
303 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
304 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
305 SAFE_FREE(dbuf.dptr);
306 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
307 return False;
309 if (tdb_delete(tdb_drivers, kbuf) != 0) {
310 SAFE_FREE(dbuf.dptr);
311 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
312 return False;
316 SAFE_FREE(dbuf.dptr);
319 return True;
322 /*******************************************************************
323 Fix an issue with security descriptors. Printer sec_desc must
324 use more than the generic bits that were previously used
325 in <= 3.0.14a. They must also have a owner and group SID assigned.
326 Otherwise, any printers than have been migrated to a Windows
327 host using printmig.exe will not be accessible.
328 *******************************************************************/
330 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
331 TDB_DATA data, void *state )
333 NTSTATUS status;
334 SEC_DESC_BUF *sd_orig = NULL;
335 SEC_DESC_BUF *sd_new, *sd_store;
336 SEC_DESC *sec, *new_sec;
337 TALLOC_CTX *ctx = state;
338 int result, i;
339 uint32 sd_size;
340 size_t size_new_sec;
342 if (!data.dptr || data.dsize == 0) {
343 return 0;
346 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
347 return 0;
350 /* upgrade the security descriptor */
352 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
353 if (!NT_STATUS_IS_OK(status)) {
354 /* delete bad entries */
355 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
356 (const char *)key.dptr ));
357 tdb_delete( tdb_printers, key );
358 return 0;
361 if (!sd_orig) {
362 return 0;
364 sec = sd_orig->sd;
366 /* is this even valid? */
368 if ( !sec->dacl ) {
369 return 0;
372 /* update access masks */
374 for ( i=0; i<sec->dacl->num_aces; i++ ) {
375 switch ( sec->dacl->aces[i].access_mask ) {
376 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
377 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
378 break;
380 case GENERIC_ALL_ACCESS:
381 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
382 break;
384 case READ_CONTROL_ACCESS:
385 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
387 default: /* no change */
388 break;
392 /* create a new SEC_DESC with the appropriate owner and group SIDs */
394 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
395 &global_sid_Builtin_Administrators,
396 &global_sid_Builtin_Administrators,
397 NULL, NULL, &size_new_sec );
398 if (!new_sec) {
399 return 0;
401 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
402 if (!sd_new) {
403 return 0;
406 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
407 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
408 return 0;
411 /* store it back */
413 sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
414 + sizeof(SEC_DESC_BUF);
416 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
417 if (!NT_STATUS_IS_OK(status)) {
418 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
419 return 0;
422 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
424 /* 0 to continue and non-zero to stop traversal */
426 return (result == -1);
429 /*******************************************************************
430 *******************************************************************/
432 static bool upgrade_to_version_4(void)
434 TALLOC_CTX *ctx;
435 int result;
437 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
439 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
440 return False;
442 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
444 talloc_destroy( ctx );
446 return ( result != -1 );
449 /*******************************************************************
450 Fix an issue with security descriptors. Printer sec_desc must
451 use more than the generic bits that were previously used
452 in <= 3.0.14a. They must also have a owner and group SID assigned.
453 Otherwise, any printers than have been migrated to a Windows
454 host using printmig.exe will not be accessible.
455 *******************************************************************/
457 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
458 TDB_DATA data, void *state )
460 TALLOC_CTX *ctx = talloc_tos();
461 TDB_DATA new_key;
463 if (!data.dptr || data.dsize == 0)
464 return 0;
466 /* upgrade printer records and security descriptors */
468 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
469 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
471 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
472 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
474 else {
475 /* ignore this record */
476 return 0;
479 /* delete the original record and store under the normalized key */
481 if ( tdb_delete( the_tdb, key ) != 0 ) {
482 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
483 key.dptr));
484 return 1;
487 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
488 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
489 key.dptr));
490 return 1;
493 return 0;
496 /*******************************************************************
497 *******************************************************************/
499 static bool upgrade_to_version_5(void)
501 TALLOC_CTX *ctx;
502 int result;
504 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
506 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
507 return False;
509 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
511 talloc_destroy( ctx );
513 return ( result != -1 );
516 /****************************************************************************
517 Open the NT printing tdbs. Done once before fork().
518 ****************************************************************************/
520 bool nt_printing_init(struct messaging_context *msg_ctx)
522 const char *vstring = "INFO/version";
523 WERROR win_rc;
524 int32 vers_id;
526 if ( tdb_drivers && tdb_printers && tdb_forms )
527 return True;
529 if (tdb_drivers)
530 tdb_close(tdb_drivers);
531 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
532 if (!tdb_drivers) {
533 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
534 state_path("ntdrivers.tdb"), strerror(errno) ));
535 return False;
538 if (tdb_printers)
539 tdb_close(tdb_printers);
540 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
541 if (!tdb_printers) {
542 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
543 state_path("ntprinters.tdb"), strerror(errno) ));
544 return False;
547 if (tdb_forms)
548 tdb_close(tdb_forms);
549 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
550 if (!tdb_forms) {
551 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
552 state_path("ntforms.tdb"), strerror(errno) ));
553 return False;
556 /* handle a Samba upgrade */
558 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
559 if (vers_id == -1) {
560 DEBUG(10, ("Fresh database\n"));
561 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
562 vers_id = NTDRIVERS_DATABASE_VERSION_5;
565 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
567 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
568 if (!upgrade_to_version_3())
569 return False;
570 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
571 vers_id = NTDRIVERS_DATABASE_VERSION_3;
574 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
575 /* Written on a bigendian machine with old fetch_int code. Save as le. */
576 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
577 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
578 vers_id = NTDRIVERS_DATABASE_VERSION_3;
581 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
582 if ( !upgrade_to_version_4() )
583 return False;
584 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
585 vers_id = NTDRIVERS_DATABASE_VERSION_4;
588 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
589 if ( !upgrade_to_version_5() )
590 return False;
591 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
592 vers_id = NTDRIVERS_DATABASE_VERSION_5;
596 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
597 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
598 return False;
602 update_c_setprinter(True);
605 * register callback to handle updating printers as new
606 * drivers are installed
609 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
610 do_drv_upgrade_printer);
613 * register callback to handle updating printer data
614 * when a driver is initialized
617 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
618 reset_all_printerdata);
620 /* of course, none of the message callbacks matter if you don't
621 tell messages.c that you interested in receiving PRINT_GENERAL
622 msgs. This is done in claim_connection() */
625 if ( lp_security() == SEC_ADS ) {
626 win_rc = check_published_printers();
627 if (!W_ERROR_IS_OK(win_rc))
628 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
631 return True;
634 /*******************************************************************
635 Function to allow filename parsing "the old way".
636 ********************************************************************/
638 NTSTATUS driver_unix_convert(connection_struct *conn,
639 const char *old_name,
640 struct smb_filename **smb_fname)
642 NTSTATUS status;
643 TALLOC_CTX *ctx = talloc_tos();
644 char *name = talloc_strdup(ctx, old_name);
646 if (!name) {
647 return NT_STATUS_NO_MEMORY;
649 unix_format(name);
650 name = unix_clean_name(ctx, name);
651 if (!name) {
652 return NT_STATUS_NO_MEMORY;
654 trim_string(name,"/","/");
656 status = unix_convert(ctx, conn, name, smb_fname, 0);
657 if (!NT_STATUS_IS_OK(status)) {
658 return NT_STATUS_NO_MEMORY;
661 return NT_STATUS_OK;
664 /*******************************************************************
665 tdb traversal function for counting printers.
666 ********************************************************************/
668 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
669 TDB_DATA data, void *context)
671 int *printer_count = (int*)context;
673 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
674 (*printer_count)++;
675 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
678 return 0;
681 /*******************************************************************
682 Update the spooler global c_setprinter. This variable is initialized
683 when the parent smbd starts with the number of existing printers. It
684 is monotonically increased by the current number of printers *after*
685 each add or delete printer RPC. Only Microsoft knows why... JRR020119
686 ********************************************************************/
688 uint32 update_c_setprinter(bool initialize)
690 int32 c_setprinter;
691 int32 printer_count = 0;
693 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
695 /* Traverse the tdb, counting the printers */
696 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
698 /* If initializing, set c_setprinter to current printers count
699 * otherwise, bump it by the current printer count
701 if (!initialize)
702 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
703 else
704 c_setprinter = printer_count;
706 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
707 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
709 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
711 return (uint32)c_setprinter;
714 /*******************************************************************
715 Get the spooler global c_setprinter, accounting for initialization.
716 ********************************************************************/
718 uint32 get_c_setprinter(void)
720 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
722 if (c_setprinter == (int32)-1)
723 c_setprinter = update_c_setprinter(True);
725 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
727 return (uint32)c_setprinter;
730 /****************************************************************************
731 Get builtin form struct list.
732 ****************************************************************************/
734 int get_builtin_ntforms(nt_forms_struct **list)
736 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
737 if (!*list) {
738 return 0;
740 return ARRAY_SIZE(default_forms);
743 /****************************************************************************
744 get a builtin form struct
745 ****************************************************************************/
747 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
749 int i;
750 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
751 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
752 if (strequal(form_name,default_forms[i].name)) {
753 DEBUGADD(6,("Found builtin form %s \n", form_name));
754 memcpy(form,&default_forms[i],sizeof(*form));
755 return true;
759 return false;
762 /****************************************************************************
763 get a form struct list.
764 ****************************************************************************/
766 int get_ntforms(nt_forms_struct **list)
768 TDB_DATA kbuf, newkey, dbuf;
769 nt_forms_struct form;
770 int ret;
771 int i;
772 int n = 0;
774 *list = NULL;
776 for (kbuf = tdb_firstkey(tdb_forms);
777 kbuf.dptr;
778 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
780 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
781 continue;
783 dbuf = tdb_fetch(tdb_forms, kbuf);
784 if (!dbuf.dptr)
785 continue;
787 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
788 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
789 &i, &form.flag, &form.width, &form.length, &form.left,
790 &form.top, &form.right, &form.bottom);
791 SAFE_FREE(dbuf.dptr);
792 if (ret != dbuf.dsize)
793 continue;
795 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
796 if (!*list) {
797 DEBUG(0,("get_ntforms: Realloc fail.\n"));
798 return 0;
800 (*list)[n] = form;
801 n++;
805 return n;
808 /****************************************************************************
809 write a form struct list
810 ****************************************************************************/
812 int write_ntforms(nt_forms_struct **list, int number)
814 TALLOC_CTX *ctx = talloc_tos();
815 char *buf = NULL;
816 char *key = NULL;
817 int len;
818 TDB_DATA dbuf;
819 int i;
821 for (i=0;i<number;i++) {
822 /* save index, so list is rebuilt in correct order */
823 len = tdb_pack(NULL, 0, "dddddddd",
824 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
825 (*list)[i].left, (*list)[i].top, (*list)[i].right,
826 (*list)[i].bottom);
827 if (!len) {
828 continue;
830 buf = TALLOC_ARRAY(ctx, char, len);
831 if (!buf) {
832 return 0;
834 len = tdb_pack((uint8 *)buf, len, "dddddddd",
835 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
836 (*list)[i].left, (*list)[i].top, (*list)[i].right,
837 (*list)[i].bottom);
838 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
839 if (!key) {
840 return 0;
842 dbuf.dsize = len;
843 dbuf.dptr = (uint8 *)buf;
844 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
845 TALLOC_FREE(key);
846 TALLOC_FREE(buf);
847 break;
849 TALLOC_FREE(key);
850 TALLOC_FREE(buf);
853 return i;
856 /****************************************************************************
857 add a form struct at the end of the list
858 ****************************************************************************/
859 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
861 int n=0;
862 bool update;
865 * NT tries to add forms even when
866 * they are already in the base
867 * only update the values if already present
870 update=False;
872 for (n=0; n<*count; n++) {
873 if ( strequal((*list)[n].name, form->form_name) ) {
874 update=True;
875 break;
879 if (update==False) {
880 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
881 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
882 return False;
884 fstrcpy((*list)[n].name, form->form_name);
885 (*count)++;
888 (*list)[n].flag = form->flags;
889 (*list)[n].width = form->size.width;
890 (*list)[n].length = form->size.height;
891 (*list)[n].left = form->area.left;
892 (*list)[n].top = form->area.top;
893 (*list)[n].right = form->area.right;
894 (*list)[n].bottom = form->area.bottom;
896 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
897 update ? "updated" : "added", form->form_name));
899 return True;
902 /****************************************************************************
903 Delete a named form struct.
904 ****************************************************************************/
906 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
908 char *key = NULL;
909 int n=0;
911 *ret = WERR_OK;
913 for (n=0; n<*count; n++) {
914 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
915 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
916 break;
920 if (n == *count) {
921 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
922 *ret = WERR_INVALID_PARAM;
923 return False;
926 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
927 *ret = WERR_NOMEM;
928 return false;
930 if (tdb_delete_bystring(tdb_forms, key) != 0) {
931 SAFE_FREE(key);
932 *ret = WERR_NOMEM;
933 return False;
935 SAFE_FREE(key);
936 return true;
939 /****************************************************************************
940 Update a form struct.
941 ****************************************************************************/
943 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
945 int n=0;
947 DEBUG(106, ("[%s]\n", form->form_name));
948 for (n=0; n<count; n++) {
949 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
950 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
951 break;
954 if (n==count) return;
956 (*list)[n].flag = form->flags;
957 (*list)[n].width = form->size.width;
958 (*list)[n].length = form->size.height;
959 (*list)[n].left = form->area.left;
960 (*list)[n].top = form->area.top;
961 (*list)[n].right = form->area.right;
962 (*list)[n].bottom = form->area.bottom;
965 /****************************************************************************
966 Get the nt drivers list.
967 Traverse the database and look-up the matching names.
968 ****************************************************************************/
969 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
971 int total=0;
972 const char *short_archi;
973 char *key, *key8;
974 TDB_DATA kbuf, newkey;
976 short_archi = get_short_archi(architecture);
977 if (!short_archi) {
978 return 0;
981 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
982 short_archi, version) < 0) {
983 return 0;
986 if (asprintf(&key8, "%s%s/%d/", DRIVERS_PREFIX8,
987 short_archi, version) < 0) {
988 SAFE_FREE(key);
989 return 0;
992 for (kbuf = tdb_firstkey(tdb_drivers);
993 kbuf.dptr;
994 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
996 if ((strncmp((const char *)kbuf.dptr, key, strlen(key)) == 0) ||
997 (strncmp((const char *)kbuf.dptr, key8, strlen(key8)) == 0)) {
999 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
1000 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
1001 SAFE_FREE(key);
1002 SAFE_FREE(key8);
1003 return -1;
1006 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) == 0) {
1007 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1008 } else if (strncmp((const char *)kbuf.dptr, key8, strlen(key8)) == 0) {
1009 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key8));
1010 } else {
1011 continue;
1013 total++;
1017 SAFE_FREE(key);
1018 SAFE_FREE(key8);
1020 return(total);
1023 /****************************************************************************
1024 Function to do the mapping between the long architecture name and
1025 the short one.
1026 ****************************************************************************/
1028 const char *get_short_archi(const char *long_archi)
1030 int i=-1;
1032 DEBUG(107,("Getting architecture dependant directory\n"));
1033 do {
1034 i++;
1035 } while ( (archi_table[i].long_archi!=NULL ) &&
1036 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1038 if (archi_table[i].long_archi==NULL) {
1039 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1040 return NULL;
1043 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1045 DEBUGADD(108,("index: [%d]\n", i));
1046 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1047 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1049 return archi_table[i].short_archi;
1052 /****************************************************************************
1053 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1054 There are two case to be covered here: PE (Portable Executable) and NE (New
1055 Executable) files. Both files support the same INFO structure, but PE files
1056 store the signature in unicode, and NE files store it as !unicode.
1057 returns -1 on error, 1 on version info found, and 0 on no version info found.
1058 ****************************************************************************/
1060 int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1062 int i;
1063 char *buf = NULL;
1064 ssize_t byte_count;
1066 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1067 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1068 fname, DOS_HEADER_SIZE));
1069 goto error_exit;
1072 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1073 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1074 fname, (unsigned long)byte_count));
1075 goto no_version_info;
1078 /* Is this really a DOS header? */
1079 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1080 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1081 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1082 goto no_version_info;
1085 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1086 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1087 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1088 fname, errno));
1089 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1090 goto no_version_info;
1093 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1094 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1095 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1096 fname, (unsigned long)byte_count));
1097 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1098 goto no_version_info;
1101 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1102 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1103 unsigned int num_sections;
1104 unsigned int section_table_bytes;
1106 /* Just skip over optional header to get to section table */
1107 if (SMB_VFS_LSEEK(fsp,
1108 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1109 SEEK_CUR) == (SMB_OFF_T)-1) {
1110 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1111 fname, errno));
1112 goto error_exit;
1115 /* get the section table */
1116 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1117 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1118 if (section_table_bytes == 0)
1119 goto error_exit;
1121 SAFE_FREE(buf);
1122 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1123 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1124 fname, section_table_bytes));
1125 goto error_exit;
1128 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1129 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1130 fname, (unsigned long)byte_count));
1131 goto error_exit;
1134 /* Iterate the section table looking for the resource section ".rsrc" */
1135 for (i = 0; i < num_sections; i++) {
1136 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1138 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1139 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1140 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1142 if (section_bytes == 0)
1143 goto error_exit;
1145 SAFE_FREE(buf);
1146 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1147 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1148 fname, section_bytes));
1149 goto error_exit;
1152 /* Seek to the start of the .rsrc section info */
1153 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1154 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1155 fname, errno));
1156 goto error_exit;
1159 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1160 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1161 fname, (unsigned long)byte_count));
1162 goto error_exit;
1165 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1166 goto error_exit;
1168 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1169 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1170 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1171 /* Align to next long address */
1172 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1174 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1175 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1176 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1178 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1179 fname, *major, *minor,
1180 (*major>>16)&0xffff, *major&0xffff,
1181 (*minor>>16)&0xffff, *minor&0xffff));
1182 SAFE_FREE(buf);
1183 return 1;
1190 /* Version info not found, fall back to origin date/time */
1191 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1192 SAFE_FREE(buf);
1193 return 0;
1195 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1196 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1197 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1198 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1199 /* At this point, we assume the file is in error. It still could be somthing
1200 * else besides a NE file, but it unlikely at this point. */
1201 goto error_exit;
1204 /* Allocate a bit more space to speed up things */
1205 SAFE_FREE(buf);
1206 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1207 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1208 fname, PE_HEADER_SIZE));
1209 goto error_exit;
1212 /* This is a HACK! I got tired of trying to sort through the messy
1213 * 'NE' file format. If anyone wants to clean this up please have at
1214 * it, but this works. 'NE' files will eventually fade away. JRR */
1215 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1216 /* Cover case that should not occur in a well formed 'NE' .dll file */
1217 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1219 for(i=0; i<byte_count; i++) {
1220 /* Fast skip past data that can't possibly match */
1221 if (buf[i] != 'V') continue;
1223 /* Potential match data crosses buf boundry, move it to beginning
1224 * of buf, and fill the buf with as much as it will hold. */
1225 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1226 int bc;
1228 memcpy(buf, &buf[i], byte_count-i);
1229 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1230 (byte_count-i))) < 0) {
1232 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1233 fname, errno));
1234 goto error_exit;
1237 byte_count = bc + (byte_count - i);
1238 if (byte_count<VS_VERSION_INFO_SIZE) break;
1240 i = 0;
1243 /* Check that the full signature string and the magic number that
1244 * follows exist (not a perfect solution, but the chances that this
1245 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1246 * twice, as it is simpler to read the code. */
1247 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1248 /* Compute skip alignment to next long address */
1249 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1250 sizeof(VS_SIGNATURE)) & 3;
1251 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1253 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1254 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1255 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1256 fname, *major, *minor,
1257 (*major>>16)&0xffff, *major&0xffff,
1258 (*minor>>16)&0xffff, *minor&0xffff));
1259 SAFE_FREE(buf);
1260 return 1;
1265 /* Version info not found, fall back to origin date/time */
1266 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1267 SAFE_FREE(buf);
1268 return 0;
1270 } else
1271 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1272 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1273 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1275 no_version_info:
1276 SAFE_FREE(buf);
1277 return 0;
1279 error_exit:
1280 SAFE_FREE(buf);
1281 return -1;
1284 /****************************************************************************
1285 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1286 share one or more files. During the MS installation process files are checked
1287 to insure that only a newer version of a shared file is installed over an
1288 older version. There are several possibilities for this comparison. If there
1289 is no previous version, the new one is newer (obviously). If either file is
1290 missing the version info structure, compare the creation date (on Unix use
1291 the modification date). Otherwise chose the numerically larger version number.
1292 ****************************************************************************/
1294 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1296 bool use_version = true;
1298 uint32 new_major;
1299 uint32 new_minor;
1300 time_t new_create_time;
1302 uint32 old_major;
1303 uint32 old_minor;
1304 time_t old_create_time;
1306 struct smb_filename *smb_fname = NULL;
1307 files_struct *fsp = NULL;
1308 SMB_STRUCT_STAT st;
1310 NTSTATUS status;
1311 int ret;
1313 SET_STAT_INVALID(st);
1314 new_create_time = (time_t)0;
1315 old_create_time = (time_t)0;
1317 /* Get file version info (if available) for previous file (if it exists) */
1318 status = driver_unix_convert(conn, old_file, &smb_fname);
1319 if (!NT_STATUS_IS_OK(status)) {
1320 goto error_exit;
1323 status = SMB_VFS_CREATE_FILE(
1324 conn, /* conn */
1325 NULL, /* req */
1326 0, /* root_dir_fid */
1327 smb_fname, /* fname */
1328 FILE_GENERIC_READ, /* access_mask */
1329 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1330 FILE_OPEN, /* create_disposition*/
1331 0, /* create_options */
1332 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1333 INTERNAL_OPEN_ONLY, /* oplock_request */
1334 0, /* allocation_size */
1335 NULL, /* sd */
1336 NULL, /* ea_list */
1337 &fsp, /* result */
1338 NULL); /* pinfo */
1340 if (!NT_STATUS_IS_OK(status)) {
1341 /* Old file not found, so by definition new file is in fact newer */
1342 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1343 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1344 errno));
1345 ret = 1;
1346 goto done;
1348 } else {
1349 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1350 if (ret == -1) {
1351 goto error_exit;
1354 if (!ret) {
1355 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1356 old_file));
1357 use_version = false;
1358 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1359 goto error_exit;
1361 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1362 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1363 (long)old_create_time));
1366 close_file(NULL, fsp, NORMAL_CLOSE);
1367 fsp = NULL;
1369 /* Get file version info (if available) for new file */
1370 status = driver_unix_convert(conn, new_file, &smb_fname);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 goto error_exit;
1375 status = SMB_VFS_CREATE_FILE(
1376 conn, /* conn */
1377 NULL, /* req */
1378 0, /* root_dir_fid */
1379 smb_fname, /* fname */
1380 FILE_GENERIC_READ, /* access_mask */
1381 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1382 FILE_OPEN, /* create_disposition*/
1383 0, /* create_options */
1384 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1385 INTERNAL_OPEN_ONLY, /* oplock_request */
1386 0, /* allocation_size */
1387 NULL, /* sd */
1388 NULL, /* ea_list */
1389 &fsp, /* result */
1390 NULL); /* pinfo */
1392 if (!NT_STATUS_IS_OK(status)) {
1393 /* New file not found, this shouldn't occur if the caller did its job */
1394 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1395 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1396 goto error_exit;
1398 } else {
1399 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1400 if (ret == -1) {
1401 goto error_exit;
1404 if (!ret) {
1405 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1406 new_file));
1407 use_version = false;
1408 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1409 goto error_exit;
1411 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1412 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1413 (long)new_create_time));
1416 close_file(NULL, fsp, NORMAL_CLOSE);
1417 fsp = NULL;
1419 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1420 /* Compare versions and choose the larger version number */
1421 if (new_major > old_major ||
1422 (new_major == old_major && new_minor > old_minor)) {
1424 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1425 ret = 1;
1426 goto done;
1428 else {
1429 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1430 ret = 0;
1431 goto done;
1434 } else {
1435 /* Compare modification time/dates and choose the newest time/date */
1436 if (new_create_time > old_create_time) {
1437 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1438 ret = 1;
1439 goto done;
1441 else {
1442 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1443 ret = 0;
1444 goto done;
1448 error_exit:
1449 if(fsp)
1450 close_file(NULL, fsp, NORMAL_CLOSE);
1451 ret = -1;
1452 done:
1453 TALLOC_FREE(smb_fname);
1454 return ret;
1457 /****************************************************************************
1458 Determine the correct cVersion associated with an architecture and driver
1459 ****************************************************************************/
1460 static uint32 get_correct_cversion(struct pipes_struct *p,
1461 const char *architecture,
1462 const char *driverpath_in,
1463 WERROR *perr)
1465 int cversion;
1466 NTSTATUS nt_status;
1467 struct smb_filename *smb_fname = NULL;
1468 char *driverpath = NULL;
1469 files_struct *fsp = NULL;
1470 connection_struct *conn = NULL;
1471 NTSTATUS status;
1472 char *oldcwd;
1473 fstring printdollar;
1474 int printdollar_snum;
1476 *perr = WERR_INVALID_PARAM;
1478 /* If architecture is Windows 95/98/ME, the version is always 0. */
1479 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1480 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1481 *perr = WERR_OK;
1482 return 0;
1485 /* If architecture is Windows x64, the version is always 3. */
1486 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1487 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1488 *perr = WERR_OK;
1489 return 3;
1492 fstrcpy(printdollar, "print$");
1494 printdollar_snum = find_service(printdollar);
1495 if (printdollar_snum == -1) {
1496 *perr = WERR_NO_SUCH_SHARE;
1497 return -1;
1500 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1501 lp_pathname(printdollar_snum),
1502 p->server_info, &oldcwd);
1503 if (!NT_STATUS_IS_OK(nt_status)) {
1504 DEBUG(0,("get_correct_cversion: create_conn_struct "
1505 "returned %s\n", nt_errstr(nt_status)));
1506 *perr = ntstatus_to_werror(nt_status);
1507 return -1;
1510 /* Open the driver file (Portable Executable format) and determine the
1511 * deriver the cversion. */
1512 driverpath = talloc_asprintf(talloc_tos(),
1513 "%s/%s",
1514 architecture,
1515 driverpath_in);
1516 if (!driverpath) {
1517 *perr = WERR_NOMEM;
1518 goto error_exit;
1521 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1522 if (!NT_STATUS_IS_OK(nt_status)) {
1523 *perr = ntstatus_to_werror(nt_status);
1524 goto error_exit;
1527 nt_status = vfs_file_exist(conn, smb_fname);
1528 if (!NT_STATUS_IS_OK(nt_status)) {
1529 *perr = WERR_BADFILE;
1530 goto error_exit;
1533 status = SMB_VFS_CREATE_FILE(
1534 conn, /* conn */
1535 NULL, /* req */
1536 0, /* root_dir_fid */
1537 smb_fname, /* fname */
1538 FILE_GENERIC_READ, /* access_mask */
1539 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1540 FILE_OPEN, /* create_disposition*/
1541 0, /* create_options */
1542 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1543 INTERNAL_OPEN_ONLY, /* oplock_request */
1544 0, /* allocation_size */
1545 NULL, /* sd */
1546 NULL, /* ea_list */
1547 &fsp, /* result */
1548 NULL); /* pinfo */
1550 if (!NT_STATUS_IS_OK(status)) {
1551 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1552 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1553 *perr = WERR_ACCESS_DENIED;
1554 goto error_exit;
1555 } else {
1556 uint32 major;
1557 uint32 minor;
1558 int ret;
1560 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1561 if (ret == -1) goto error_exit;
1563 if (!ret) {
1564 DEBUG(6,("get_correct_cversion: Version info not "
1565 "found [%s]\n",
1566 smb_fname_str_dbg(smb_fname)));
1567 goto error_exit;
1571 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1572 * for more details. Version in this case is not just the version of the
1573 * file, but the version in the sense of kernal mode (2) vs. user mode
1574 * (3) drivers. Other bits of the version fields are the version info.
1575 * JRR 010716
1577 cversion = major & 0x0000ffff;
1578 switch (cversion) {
1579 case 2: /* WinNT drivers */
1580 case 3: /* Win2K drivers */
1581 break;
1583 default:
1584 DEBUG(6,("get_correct_cversion: cversion "
1585 "invalid [%s] cversion = %d\n",
1586 smb_fname_str_dbg(smb_fname),
1587 cversion));
1588 goto error_exit;
1591 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1592 " = 0x%x minor = 0x%x\n",
1593 smb_fname_str_dbg(smb_fname), major, minor));
1596 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1597 smb_fname_str_dbg(smb_fname), cversion));
1599 goto done;
1601 error_exit:
1602 cversion = -1;
1603 done:
1604 TALLOC_FREE(smb_fname);
1605 if (fsp != NULL) {
1606 close_file(NULL, fsp, NORMAL_CLOSE);
1608 if (conn != NULL) {
1609 vfs_ChDir(conn, oldcwd);
1610 conn_free(conn);
1612 if (cversion != -1) {
1613 *perr = WERR_OK;
1615 return cversion;
1618 /****************************************************************************
1619 ****************************************************************************/
1621 #define strip_driver_path(_mem_ctx, _element) do { \
1622 if ((_p = strrchr((_element), '\\')) != NULL) { \
1623 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1624 W_ERROR_HAVE_NO_MEMORY((_element)); \
1626 } while (0);
1628 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1629 struct pipes_struct *rpc_pipe,
1630 const char *architecture,
1631 const char **driver_path,
1632 const char **data_file,
1633 const char **config_file,
1634 const char **help_file,
1635 struct spoolss_StringArray *dependent_files,
1636 uint32_t *version)
1638 const char *short_architecture;
1639 int i;
1640 WERROR err;
1641 char *_p;
1643 /* clean up the driver name.
1644 * we can get .\driver.dll
1645 * or worse c:\windows\system\driver.dll !
1647 /* using an intermediate string to not have overlaping memcpy()'s */
1649 strip_driver_path(mem_ctx, *driver_path);
1650 strip_driver_path(mem_ctx, *data_file);
1651 strip_driver_path(mem_ctx, *config_file);
1652 strip_driver_path(mem_ctx, *help_file);
1654 if (dependent_files && dependent_files->string) {
1655 for (i=0; dependent_files->string[i]; i++) {
1656 strip_driver_path(mem_ctx, dependent_files->string[i]);
1660 short_architecture = get_short_archi(architecture);
1661 if (!short_architecture) {
1662 return WERR_UNKNOWN_PRINTER_DRIVER;
1665 /* jfm:7/16/2000 the client always sends the cversion=0.
1666 * The server should check which version the driver is by reading
1667 * the PE header of driver->driverpath.
1669 * For Windows 95/98 the version is 0 (so the value sent is correct)
1670 * For Windows NT (the architecture doesn't matter)
1671 * NT 3.1: cversion=0
1672 * NT 3.5/3.51: cversion=1
1673 * NT 4: cversion=2
1674 * NT2K: cversion=3
1677 *version = get_correct_cversion(rpc_pipe, short_architecture,
1678 *driver_path, &err);
1679 if (*version == -1) {
1680 return err;
1683 return WERR_OK;
1686 /****************************************************************************
1687 ****************************************************************************/
1689 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1690 struct spoolss_AddDriverInfoCtr *r)
1692 switch (r->level) {
1693 case 3:
1694 return clean_up_driver_struct_level(r, rpc_pipe,
1695 r->info.info3->architecture,
1696 &r->info.info3->driver_path,
1697 &r->info.info3->data_file,
1698 &r->info.info3->config_file,
1699 &r->info.info3->help_file,
1700 r->info.info3->dependent_files,
1701 &r->info.info3->version);
1702 case 6:
1703 return clean_up_driver_struct_level(r, rpc_pipe,
1704 r->info.info6->architecture,
1705 &r->info.info6->driver_path,
1706 &r->info.info6->data_file,
1707 &r->info.info6->config_file,
1708 &r->info.info6->help_file,
1709 r->info.info6->dependent_files,
1710 &r->info.info6->version);
1711 case 8:
1712 return clean_up_driver_struct_level(r, rpc_pipe,
1713 r->info.info8->architecture,
1714 &r->info.info8->driver_path,
1715 &r->info.info8->data_file,
1716 &r->info.info8->config_file,
1717 &r->info.info8->help_file,
1718 r->info.info8->dependent_files,
1719 &r->info.info8->version);
1720 default:
1721 return WERR_NOT_SUPPORTED;
1725 /****************************************************************************
1726 This function sucks and should be replaced. JRA.
1727 ****************************************************************************/
1729 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1730 const struct spoolss_AddDriverInfo6 *src)
1732 dst->version = src->version;
1734 dst->driver_name = src->driver_name;
1735 dst->architecture = src->architecture;
1736 dst->driver_path = src->driver_path;
1737 dst->data_file = src->data_file;
1738 dst->config_file = src->config_file;
1739 dst->help_file = src->help_file;
1740 dst->monitor_name = src->monitor_name;
1741 dst->default_datatype = src->default_datatype;
1742 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1743 dst->dependent_files = src->dependent_files;
1746 /****************************************************************************
1747 This function sucks and should be replaced. JRA.
1748 ****************************************************************************/
1750 static void convert_level_8_to_level3(struct spoolss_AddDriverInfo3 *dst,
1751 const struct spoolss_AddDriverInfo8 *src)
1753 dst->version = src->version;
1755 dst->driver_name = src->driver_name;
1756 dst->architecture = src->architecture;
1757 dst->driver_path = src->driver_path;
1758 dst->data_file = src->data_file;
1759 dst->config_file = src->config_file;
1760 dst->help_file = src->help_file;
1761 dst->monitor_name = src->monitor_name;
1762 dst->default_datatype = src->default_datatype;
1763 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1764 dst->dependent_files = src->dependent_files;
1767 /****************************************************************************
1768 ****************************************************************************/
1770 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1771 connection_struct *conn,
1772 const char *driver_file,
1773 const char *short_architecture,
1774 uint32_t driver_version,
1775 uint32_t version)
1777 struct smb_filename *smb_fname_old = NULL;
1778 struct smb_filename *smb_fname_new = NULL;
1779 char *old_name = NULL;
1780 char *new_name = NULL;
1781 NTSTATUS status;
1782 WERROR ret;
1784 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1785 short_architecture, driver_file);
1786 W_ERROR_HAVE_NO_MEMORY(old_name);
1788 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1789 short_architecture, driver_version, driver_file);
1790 if (new_name == NULL) {
1791 TALLOC_FREE(old_name);
1792 return WERR_NOMEM;
1795 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1797 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 ret = WERR_NOMEM;
1800 goto out;
1803 /* Setup a synthetic smb_filename struct */
1804 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1805 if (!smb_fname_new) {
1806 ret = WERR_NOMEM;
1807 goto out;
1810 smb_fname_new->base_name = new_name;
1812 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1813 "'%s'\n", smb_fname_old->base_name,
1814 smb_fname_new->base_name));
1816 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1817 OPENX_FILE_EXISTS_TRUNCATE |
1818 OPENX_FILE_CREATE_IF_NOT_EXIST,
1819 0, false);
1821 if (!NT_STATUS_IS_OK(status)) {
1822 DEBUG(0,("move_driver_file_to_download_area: Unable "
1823 "to rename [%s] to [%s]: %s\n",
1824 smb_fname_old->base_name, new_name,
1825 nt_errstr(status)));
1826 ret = WERR_ACCESS_DENIED;
1827 goto out;
1831 ret = WERR_OK;
1832 out:
1833 TALLOC_FREE(smb_fname_old);
1834 TALLOC_FREE(smb_fname_new);
1835 return ret;
1838 WERROR move_driver_to_download_area(struct pipes_struct *p,
1839 struct spoolss_AddDriverInfoCtr *r,
1840 WERROR *perr)
1842 struct spoolss_AddDriverInfo3 *driver;
1843 struct spoolss_AddDriverInfo3 converted_driver;
1844 const char *short_architecture;
1845 struct smb_filename *smb_dname = NULL;
1846 char *new_dir = NULL;
1847 connection_struct *conn = NULL;
1848 NTSTATUS nt_status;
1849 int i;
1850 TALLOC_CTX *ctx = talloc_tos();
1851 int ver = 0;
1852 char *oldcwd;
1853 fstring printdollar;
1854 int printdollar_snum;
1856 *perr = WERR_OK;
1858 switch (r->level) {
1859 case 3:
1860 driver = r->info.info3;
1861 break;
1862 case 6:
1863 convert_level_6_to_level3(&converted_driver, r->info.info6);
1864 driver = &converted_driver;
1865 break;
1866 case 8:
1867 convert_level_8_to_level3(&converted_driver, r->info.info8);
1868 driver = &converted_driver;
1869 break;
1870 default:
1871 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1872 return WERR_UNKNOWN_LEVEL;
1875 short_architecture = get_short_archi(driver->architecture);
1876 if (!short_architecture) {
1877 return WERR_UNKNOWN_PRINTER_DRIVER;
1880 fstrcpy(printdollar, "print$");
1882 printdollar_snum = find_service(printdollar);
1883 if (printdollar_snum == -1) {
1884 *perr = WERR_NO_SUCH_SHARE;
1885 return WERR_NO_SUCH_SHARE;
1888 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1889 lp_pathname(printdollar_snum),
1890 p->server_info, &oldcwd);
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1892 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1893 "returned %s\n", nt_errstr(nt_status)));
1894 *perr = ntstatus_to_werror(nt_status);
1895 return *perr;
1898 new_dir = talloc_asprintf(ctx,
1899 "%s/%d",
1900 short_architecture,
1901 driver->version);
1902 if (!new_dir) {
1903 *perr = WERR_NOMEM;
1904 goto err_exit;
1906 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1907 if (!NT_STATUS_IS_OK(nt_status)) {
1908 *perr = WERR_NOMEM;
1909 goto err_exit;
1912 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1914 create_directory(conn, NULL, smb_dname);
1916 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1917 * listed for this driver which has already been moved, skip it (note:
1918 * drivers may list the same file name several times. Then check if the
1919 * file already exists in archi\version\, if so, check that the version
1920 * info (or time stamps if version info is unavailable) is newer (or the
1921 * date is later). If it is, move it to archi\version\filexxx.yyy.
1922 * Otherwise, delete the file.
1924 * If a file is not moved to archi\version\ because of an error, all the
1925 * rest of the 'unmoved' driver files are removed from archi\. If one or
1926 * more of the driver's files was already moved to archi\version\, it
1927 * potentially leaves the driver in a partially updated state. Version
1928 * trauma will most likely occur if an client attempts to use any printer
1929 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1930 * done is appropriate... later JRR
1933 DEBUG(5,("Moving files now !\n"));
1935 if (driver->driver_path && strlen(driver->driver_path)) {
1937 *perr = move_driver_file_to_download_area(ctx,
1938 conn,
1939 driver->driver_path,
1940 short_architecture,
1941 driver->version,
1942 ver);
1943 if (!W_ERROR_IS_OK(*perr)) {
1944 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1945 ver = -1;
1947 goto err_exit;
1951 if (driver->data_file && strlen(driver->data_file)) {
1952 if (!strequal(driver->data_file, driver->driver_path)) {
1954 *perr = move_driver_file_to_download_area(ctx,
1955 conn,
1956 driver->data_file,
1957 short_architecture,
1958 driver->version,
1959 ver);
1960 if (!W_ERROR_IS_OK(*perr)) {
1961 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1962 ver = -1;
1964 goto err_exit;
1969 if (driver->config_file && strlen(driver->config_file)) {
1970 if (!strequal(driver->config_file, driver->driver_path) &&
1971 !strequal(driver->config_file, driver->data_file)) {
1973 *perr = move_driver_file_to_download_area(ctx,
1974 conn,
1975 driver->config_file,
1976 short_architecture,
1977 driver->version,
1978 ver);
1979 if (!W_ERROR_IS_OK(*perr)) {
1980 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1981 ver = -1;
1983 goto err_exit;
1988 if (driver->help_file && strlen(driver->help_file)) {
1989 if (!strequal(driver->help_file, driver->driver_path) &&
1990 !strequal(driver->help_file, driver->data_file) &&
1991 !strequal(driver->help_file, driver->config_file)) {
1993 *perr = move_driver_file_to_download_area(ctx,
1994 conn,
1995 driver->help_file,
1996 short_architecture,
1997 driver->version,
1998 ver);
1999 if (!W_ERROR_IS_OK(*perr)) {
2000 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2001 ver = -1;
2003 goto err_exit;
2008 if (driver->dependent_files && driver->dependent_files->string) {
2009 for (i=0; driver->dependent_files->string[i]; i++) {
2010 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
2011 !strequal(driver->dependent_files->string[i], driver->data_file) &&
2012 !strequal(driver->dependent_files->string[i], driver->config_file) &&
2013 !strequal(driver->dependent_files->string[i], driver->help_file)) {
2014 int j;
2015 for (j=0; j < i; j++) {
2016 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2017 goto NextDriver;
2021 *perr = move_driver_file_to_download_area(ctx,
2022 conn,
2023 driver->dependent_files->string[i],
2024 short_architecture,
2025 driver->version,
2026 ver);
2027 if (!W_ERROR_IS_OK(*perr)) {
2028 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2029 ver = -1;
2031 goto err_exit;
2034 NextDriver: ;
2038 err_exit:
2039 TALLOC_FREE(smb_dname);
2041 if (conn != NULL) {
2042 vfs_ChDir(conn, oldcwd);
2043 conn_free(conn);
2046 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2047 return WERR_OK;
2049 if (ver == -1) {
2050 return WERR_UNKNOWN_PRINTER_DRIVER;
2052 return (*perr);
2055 /****************************************************************************
2056 ****************************************************************************/
2058 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *r)
2060 TALLOC_CTX *ctx = talloc_tos();
2061 const char *architecture;
2062 char *directory = NULL;
2063 char *key = NULL;
2064 int i, ret;
2065 TDB_DATA dbuf;
2066 enum ndr_err_code ndr_err;
2067 DATA_BLOB blob;
2069 architecture = get_short_archi(r->architecture);
2070 if (!architecture) {
2071 return (uint32_t)-1;
2074 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2075 * \\server is added in the rpc server layer.
2076 * It does make sense to NOT store the server's name in the printer TDB.
2079 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2080 architecture, r->version);
2081 if (!directory) {
2082 return (uint32_t)-1;
2085 #define gen_full_driver_unc_path(ctx, directory, file) \
2086 do { \
2087 if (file && strlen(file)) { \
2088 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2089 } else { \
2090 file = talloc_strdup(ctx, ""); \
2092 if (!file) { \
2093 return (uint32_t)-1; \
2095 } while (0);
2097 /* .inf files do not always list a file for each of the four standard files.
2098 * Don't prepend a path to a null filename, or client claims:
2099 * "The server on which the printer resides does not have a suitable
2100 * <printer driver name> printer driver installed. Click OK if you
2101 * wish to install the driver on your local machine."
2103 gen_full_driver_unc_path(ctx, directory, r->driver_path);
2104 gen_full_driver_unc_path(ctx, directory, r->data_file);
2105 gen_full_driver_unc_path(ctx, directory, r->config_file);
2106 gen_full_driver_unc_path(ctx, directory, r->help_file);
2108 for (i=0; r->dependent_files && r->dependent_files[i]; i++) {
2109 gen_full_driver_unc_path(ctx, directory,
2110 r->dependent_files[i]);
2113 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX8,
2114 architecture, r->version, r->driver_name);
2115 if (!key) {
2116 return (uint32_t)-1;
2119 DEBUG(5,("add_a_printer_driver_8: Adding driver with key %s\n", key));
2121 ndr_err = ndr_push_struct_blob(&blob, ctx, NULL, r,
2122 (ndr_push_flags_fn_t)ndr_push_spoolss_DriverInfo8);
2123 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2124 return (uint32_t)-1;
2127 dbuf.dptr = blob.data;
2128 dbuf.dsize = blob.length;
2130 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2132 data_blob_free(&blob);
2134 if (ret) {
2135 DEBUG(0,("add_a_printer_driver_8: Adding driver with key %s failed.\n", key));
2138 return ret;
2141 /****************************************************************************
2142 ****************************************************************************/
2144 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2145 struct spoolss_DriverInfo3 *info,
2146 const char *driver, const char *arch)
2148 info->driver_name = talloc_strdup(mem_ctx, driver);
2149 if (!info->driver_name) {
2150 return WERR_NOMEM;
2153 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2154 if (!info->default_datatype) {
2155 return WERR_NOMEM;
2158 info->driver_path = talloc_strdup(mem_ctx, "");
2159 info->data_file = talloc_strdup(mem_ctx, "");
2160 info->config_file = talloc_strdup(mem_ctx, "");
2161 info->help_file = talloc_strdup(mem_ctx, "");
2162 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2163 return WERR_NOMEM;
2166 return WERR_OK;
2169 /****************************************************************************
2170 ****************************************************************************/
2172 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2173 struct spoolss_DriverInfo3 *driver,
2174 const char *drivername, const char *arch,
2175 uint32_t version)
2177 TDB_DATA dbuf;
2178 const char *architecture;
2179 int len = 0;
2180 int i;
2181 char *key = NULL;
2182 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2184 architecture = get_short_archi(arch);
2185 if ( !architecture ) {
2186 return WERR_UNKNOWN_PRINTER_DRIVER;
2189 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2191 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2192 version = 0;
2194 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2196 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2197 architecture, version, drivername) < 0) {
2198 return WERR_NOMEM;
2201 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2202 if (!dbuf.dptr) {
2203 SAFE_FREE(key);
2204 return WERR_UNKNOWN_PRINTER_DRIVER;
2207 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2208 &driver->version,
2209 name,
2210 environment,
2211 driverpath,
2212 datafile,
2213 configfile,
2214 helpfile,
2215 monitorname,
2216 defaultdatatype);
2218 driver->driver_name = talloc_strdup(mem_ctx, name);
2219 driver->architecture = talloc_strdup(mem_ctx, environment);
2220 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2221 driver->data_file = talloc_strdup(mem_ctx, datafile);
2222 driver->config_file = talloc_strdup(mem_ctx, configfile);
2223 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2224 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2225 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2227 i=0;
2229 while (len < dbuf.dsize) {
2231 fstring file;
2233 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2234 if (!driver->dependent_files ) {
2235 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2236 break;
2239 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2240 &file);
2242 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2244 i++;
2247 if (driver->dependent_files)
2248 driver->dependent_files[i] = NULL;
2250 SAFE_FREE(dbuf.dptr);
2251 SAFE_FREE(key);
2253 if (len != dbuf.dsize) {
2254 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2257 return WERR_OK;
2260 /****************************************************************************
2261 ****************************************************************************/
2263 static WERROR get_a_printer_driver_8(TALLOC_CTX *mem_ctx,
2264 struct spoolss_DriverInfo8 **driver,
2265 const char *drivername, const char *arch,
2266 uint32_t version)
2268 TDB_DATA dbuf;
2269 const char *architecture;
2270 char *key = NULL;
2271 enum ndr_err_code ndr_err;
2272 DATA_BLOB blob;
2273 struct spoolss_DriverInfo8 *r;
2275 *driver = NULL;
2277 architecture = get_short_archi(arch);
2278 if (!architecture) {
2279 return WERR_UNKNOWN_PRINTER_DRIVER;
2282 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2284 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
2285 version = 0;
2288 DEBUG(8,("get_a_printer_driver_8: [%s%s/%d/%s]\n", DRIVERS_PREFIX8,
2289 architecture, version, drivername));
2291 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX8,
2292 architecture, version, drivername) < 0) {
2293 return WERR_NOMEM;
2296 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2297 if (!dbuf.dptr) {
2298 SAFE_FREE(key);
2299 return WERR_UNKNOWN_PRINTER_DRIVER;
2302 r = talloc(mem_ctx, struct spoolss_DriverInfo8);
2303 if (!r) {
2304 SAFE_FREE(dbuf.dptr);
2305 SAFE_FREE(key);
2306 return WERR_NOMEM;
2309 blob = data_blob_const(dbuf.dptr, dbuf.dsize);
2311 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, r,
2312 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DriverInfo8);
2313 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2314 SAFE_FREE(dbuf.dptr);
2315 SAFE_FREE(key);
2316 return WERR_UNKNOWN_PRINTER_DRIVER;
2319 SAFE_FREE(dbuf.dptr);
2320 SAFE_FREE(key);
2322 *driver = r;
2324 return WERR_OK;
2327 /****************************************************************************
2328 ****************************************************************************/
2329 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2331 int len = 0;
2333 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2335 if (!nt_devmode)
2336 return len;
2338 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2339 nt_devmode->devicename,
2340 nt_devmode->formname,
2342 nt_devmode->specversion,
2343 nt_devmode->driverversion,
2344 nt_devmode->size,
2345 nt_devmode->driverextra,
2346 nt_devmode->orientation,
2347 nt_devmode->papersize,
2348 nt_devmode->paperlength,
2349 nt_devmode->paperwidth,
2350 nt_devmode->scale,
2351 nt_devmode->copies,
2352 nt_devmode->defaultsource,
2353 nt_devmode->printquality,
2354 nt_devmode->color,
2355 nt_devmode->duplex,
2356 nt_devmode->yresolution,
2357 nt_devmode->ttoption,
2358 nt_devmode->collate,
2359 nt_devmode->logpixels,
2361 nt_devmode->fields,
2362 nt_devmode->bitsperpel,
2363 nt_devmode->pelswidth,
2364 nt_devmode->pelsheight,
2365 nt_devmode->displayflags,
2366 nt_devmode->displayfrequency,
2367 nt_devmode->icmmethod,
2368 nt_devmode->icmintent,
2369 nt_devmode->mediatype,
2370 nt_devmode->dithertype,
2371 nt_devmode->reserved1,
2372 nt_devmode->reserved2,
2373 nt_devmode->panningwidth,
2374 nt_devmode->panningheight,
2375 nt_devmode->nt_dev_private);
2377 if (nt_devmode->nt_dev_private) {
2378 len += tdb_pack(buf+len, buflen-len, "B",
2379 nt_devmode->driverextra,
2380 nt_devmode->nt_dev_private);
2383 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2385 return len;
2388 /****************************************************************************
2389 Pack all values in all printer keys
2390 ***************************************************************************/
2392 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2394 int len = 0;
2395 int i, j;
2396 struct regval_blob *val;
2397 struct regval_ctr *val_ctr;
2398 char *path = NULL;
2399 int num_values;
2401 if ( !data )
2402 return 0;
2404 /* loop over all keys */
2406 for ( i=0; i<data->num_keys; i++ ) {
2407 val_ctr = data->keys[i].values;
2408 num_values = regval_ctr_numvals( val_ctr );
2410 /* pack the keyname followed by a empty value */
2412 len += tdb_pack(buf+len, buflen-len, "pPdB",
2413 &data->keys[i].name,
2414 data->keys[i].name,
2415 REG_NONE,
2417 NULL);
2419 /* now loop over all values */
2421 for ( j=0; j<num_values; j++ ) {
2422 /* pathname should be stored as <key>\<value> */
2424 val = regval_ctr_specific_value( val_ctr, j );
2425 if (asprintf(&path, "%s\\%s",
2426 data->keys[i].name,
2427 regval_name(val)) < 0) {
2428 return -1;
2431 len += tdb_pack(buf+len, buflen-len, "pPdB",
2432 val,
2433 path,
2434 regval_type(val),
2435 regval_size(val),
2436 regval_data_p(val) );
2438 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2439 SAFE_FREE(path);
2444 /* terminator */
2446 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2448 return len;
2452 /****************************************************************************
2453 Delete a printer - this just deletes the printer info file, any open
2454 handles are not affected.
2455 ****************************************************************************/
2457 uint32 del_a_printer(const char *sharename)
2459 TDB_DATA kbuf;
2460 char *printdb_path = NULL;
2461 TALLOC_CTX *ctx = talloc_tos();
2463 kbuf = make_printer_tdbkey(ctx, sharename);
2464 tdb_delete(tdb_printers, kbuf);
2466 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2467 tdb_delete(tdb_printers, kbuf);
2469 close_all_print_db();
2471 if (geteuid() == sec_initial_uid()) {
2472 if (asprintf(&printdb_path, "%s%s.tdb",
2473 cache_path("printing/"),
2474 sharename) < 0) {
2475 return (uint32)-1;
2477 unlink(printdb_path);
2478 SAFE_FREE(printdb_path);
2481 return 0;
2484 /****************************************************************************
2485 ****************************************************************************/
2486 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2488 uint8 *buf;
2489 int buflen, len;
2490 int retlen;
2491 WERROR ret;
2492 TDB_DATA kbuf, dbuf;
2495 * in addprinter: no servername and the printer is the name
2496 * in setprinter: servername is \\server
2497 * and printer is \\server\\printer
2499 * Samba manages only local printers.
2500 * we currently don't support things like i
2501 * path=\\other_server\printer
2503 * We only store the printername, not \\server\printername
2506 if ( info->servername[0] != '\0' ) {
2507 trim_string(info->printername, info->servername, NULL);
2508 trim_char(info->printername, '\\', '\0');
2509 info->servername[0]='\0';
2513 * JFM: one day I'll forget.
2514 * below that's info->portname because that's the SAMBA sharename
2515 * and I made NT 'thinks' it's the portname
2516 * the info->sharename is the thing you can name when you add a printer
2517 * that's the short-name when you create shared printer for 95/98
2518 * So I've made a limitation in SAMBA: you can only have 1 printer model
2519 * behind a SAMBA share.
2522 buf = NULL;
2523 buflen = 0;
2525 again:
2526 len = 0;
2527 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2528 info->attributes,
2529 info->priority,
2530 info->default_priority,
2531 info->starttime,
2532 info->untiltime,
2533 info->status,
2534 info->cjobs,
2535 info->averageppm,
2536 info->changeid,
2537 info->c_setprinter,
2538 info->setuptime,
2539 info->servername,
2540 info->printername,
2541 info->sharename,
2542 info->portname,
2543 info->drivername,
2544 info->comment,
2545 info->location,
2546 info->sepfile,
2547 info->printprocessor,
2548 info->datatype,
2549 info->parameters);
2551 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2552 retlen = pack_values( info->data, buf+len, buflen-len );
2553 if (retlen == -1) {
2554 ret = WERR_NOMEM;
2555 goto done;
2557 len += retlen;
2559 if (buflen != len) {
2560 buf = (uint8 *)SMB_REALLOC(buf, len);
2561 if (!buf) {
2562 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2563 ret = WERR_NOMEM;
2564 goto done;
2566 buflen = len;
2567 goto again;
2570 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2572 dbuf.dptr = buf;
2573 dbuf.dsize = len;
2575 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2577 done:
2578 if (!W_ERROR_IS_OK(ret))
2579 DEBUG(8, ("error updating printer to tdb on disk\n"));
2581 SAFE_FREE(buf);
2583 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2584 info->sharename, info->drivername, info->portname, len));
2586 return ret;
2590 /****************************************************************************
2591 Malloc and return an NT devicemode.
2592 ****************************************************************************/
2594 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2597 char adevice[MAXDEVICENAME];
2598 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2600 if (nt_devmode == NULL) {
2601 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2602 return NULL;
2605 ZERO_STRUCTP(nt_devmode);
2607 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2608 fstrcpy(nt_devmode->devicename, adevice);
2610 fstrcpy(nt_devmode->formname, "Letter");
2612 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2613 nt_devmode->driverversion = 0x0400;
2614 nt_devmode->size = 0x00DC;
2615 nt_devmode->driverextra = 0x0000;
2616 nt_devmode->fields = DEVMODE_FORMNAME |
2617 DEVMODE_TTOPTION |
2618 DEVMODE_PRINTQUALITY |
2619 DEVMODE_DEFAULTSOURCE |
2620 DEVMODE_COPIES |
2621 DEVMODE_SCALE |
2622 DEVMODE_PAPERSIZE |
2623 DEVMODE_ORIENTATION;
2624 nt_devmode->orientation = DMORIENT_PORTRAIT;
2625 nt_devmode->papersize = DMPAPER_LETTER;
2626 nt_devmode->paperlength = 0;
2627 nt_devmode->paperwidth = 0;
2628 nt_devmode->scale = 0x64;
2629 nt_devmode->copies = 1;
2630 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2631 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2632 nt_devmode->color = DMRES_MONOCHROME;
2633 nt_devmode->duplex = DMDUP_SIMPLEX;
2634 nt_devmode->yresolution = 0;
2635 nt_devmode->ttoption = DMTT_SUBDEV;
2636 nt_devmode->collate = DMCOLLATE_FALSE;
2637 nt_devmode->icmmethod = 0;
2638 nt_devmode->icmintent = 0;
2639 nt_devmode->mediatype = 0;
2640 nt_devmode->dithertype = 0;
2642 /* non utilisés par un driver d'imprimante */
2643 nt_devmode->logpixels = 0;
2644 nt_devmode->bitsperpel = 0;
2645 nt_devmode->pelswidth = 0;
2646 nt_devmode->pelsheight = 0;
2647 nt_devmode->displayflags = 0;
2648 nt_devmode->displayfrequency = 0;
2649 nt_devmode->reserved1 = 0;
2650 nt_devmode->reserved2 = 0;
2651 nt_devmode->panningwidth = 0;
2652 nt_devmode->panningheight = 0;
2654 nt_devmode->nt_dev_private = NULL;
2655 return nt_devmode;
2658 /****************************************************************************
2659 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2660 ****************************************************************************/
2662 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2664 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2666 if(nt_devmode == NULL)
2667 return;
2669 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2671 SAFE_FREE(nt_devmode->nt_dev_private);
2672 SAFE_FREE(*devmode_ptr);
2675 /****************************************************************************
2676 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2677 ****************************************************************************/
2679 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2681 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2683 if ( !info )
2684 return;
2686 free_nt_devicemode(&info->devmode);
2688 TALLOC_FREE( *info_ptr );
2692 /****************************************************************************
2693 ****************************************************************************/
2694 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2696 int len = 0;
2697 int extra_len = 0;
2698 NT_DEVICEMODE devmode;
2700 ZERO_STRUCT(devmode);
2702 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2704 if (!*nt_devmode) return len;
2706 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2707 devmode.devicename,
2708 devmode.formname,
2710 &devmode.specversion,
2711 &devmode.driverversion,
2712 &devmode.size,
2713 &devmode.driverextra,
2714 &devmode.orientation,
2715 &devmode.papersize,
2716 &devmode.paperlength,
2717 &devmode.paperwidth,
2718 &devmode.scale,
2719 &devmode.copies,
2720 &devmode.defaultsource,
2721 &devmode.printquality,
2722 &devmode.color,
2723 &devmode.duplex,
2724 &devmode.yresolution,
2725 &devmode.ttoption,
2726 &devmode.collate,
2727 &devmode.logpixels,
2729 &devmode.fields,
2730 &devmode.bitsperpel,
2731 &devmode.pelswidth,
2732 &devmode.pelsheight,
2733 &devmode.displayflags,
2734 &devmode.displayfrequency,
2735 &devmode.icmmethod,
2736 &devmode.icmintent,
2737 &devmode.mediatype,
2738 &devmode.dithertype,
2739 &devmode.reserved1,
2740 &devmode.reserved2,
2741 &devmode.panningwidth,
2742 &devmode.panningheight,
2743 &devmode.nt_dev_private);
2745 if (devmode.nt_dev_private) {
2746 /* the len in tdb_unpack is an int value and
2747 * devmode.driverextra is only a short
2749 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2750 devmode.driverextra=(uint16)extra_len;
2752 /* check to catch an invalid TDB entry so we don't segfault */
2753 if (devmode.driverextra == 0) {
2754 devmode.nt_dev_private = NULL;
2758 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2759 if (!*nt_devmode) {
2760 SAFE_FREE(devmode.nt_dev_private);
2761 return -1;
2764 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2765 if (devmode.nt_dev_private)
2766 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2768 return len;
2771 /****************************************************************************
2772 Allocate and initialize a new slot.
2773 ***************************************************************************/
2775 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2777 NT_PRINTER_KEY *d;
2778 int key_index;
2780 if ( !name || !data )
2781 return -1;
2783 /* allocate another slot in the NT_PRINTER_KEY array */
2785 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2786 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2787 return -1;
2790 data->keys = d;
2792 key_index = data->num_keys;
2794 /* initialze new key */
2796 data->keys[key_index].name = talloc_strdup( data, name );
2798 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2799 return -1;
2801 data->num_keys++;
2803 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2805 return key_index;
2808 /****************************************************************************
2809 search for a registry key name in the existing printer data
2810 ***************************************************************************/
2812 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2814 int i;
2816 for ( i=0; i<data->num_keys; i++ ) {
2817 if ( strequal( data->keys[i].name, name ) ) {
2819 /* cleanup memory */
2821 TALLOC_FREE( data->keys[i].name );
2822 TALLOC_FREE( data->keys[i].values );
2824 /* if not the end of the array, move remaining elements down one slot */
2826 data->num_keys--;
2827 if ( data->num_keys && (i < data->num_keys) )
2828 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2830 break;
2835 return data->num_keys;
2838 /****************************************************************************
2839 search for a registry key name in the existing printer data
2840 ***************************************************************************/
2842 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2844 int key_index = -1;
2845 int i;
2847 if ( !data || !name )
2848 return -1;
2850 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2852 /* loop over all existing keys */
2854 for ( i=0; i<data->num_keys; i++ ) {
2855 if ( strequal(data->keys[i].name, name) ) {
2856 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2857 key_index = i;
2858 break;
2863 return key_index;
2866 /****************************************************************************
2867 ***************************************************************************/
2869 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2871 int i, j;
2872 int key_len;
2873 int num_subkeys = 0;
2874 char *p;
2875 fstring *subkeys_ptr = NULL;
2876 fstring subkeyname;
2878 *subkeys = NULL;
2880 if ( !data )
2881 return 0;
2883 if ( !key )
2884 return -1;
2886 /* special case of asking for the top level printer data registry key names */
2888 if ( strlen(key) == 0 ) {
2889 for ( i=0; i<data->num_keys; i++ ) {
2891 /* found a match, so allocate space and copy the name */
2893 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2894 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2895 num_subkeys+1));
2896 return -1;
2899 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2900 num_subkeys++;
2903 goto done;
2906 /* asking for the subkeys of some key */
2907 /* subkey paths are stored in the key name using '\' as the delimiter */
2909 for ( i=0; i<data->num_keys; i++ ) {
2910 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2912 /* if we found the exact key, then break */
2913 key_len = strlen( key );
2914 if ( strlen(data->keys[i].name) == key_len )
2915 break;
2917 /* get subkey path */
2919 p = data->keys[i].name + key_len;
2920 if ( *p == '\\' )
2921 p++;
2922 fstrcpy( subkeyname, p );
2923 if ( (p = strchr( subkeyname, '\\' )) )
2924 *p = '\0';
2926 /* don't add a key more than once */
2928 for ( j=0; j<num_subkeys; j++ ) {
2929 if ( strequal( subkeys_ptr[j], subkeyname ) )
2930 break;
2933 if ( j != num_subkeys )
2934 continue;
2936 /* found a match, so allocate space and copy the name */
2938 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2939 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2940 num_subkeys+1));
2941 return 0;
2944 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2945 num_subkeys++;
2950 /* return error if the key was not found */
2952 if ( i == data->num_keys ) {
2953 SAFE_FREE(subkeys_ptr);
2954 return -1;
2957 done:
2958 /* tag off the end */
2960 if (num_subkeys)
2961 fstrcpy(subkeys_ptr[num_subkeys], "" );
2963 *subkeys = subkeys_ptr;
2965 return num_subkeys;
2968 #ifdef HAVE_ADS
2969 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2970 const char *sz)
2972 regval_ctr_delvalue(ctr, val_name);
2973 regval_ctr_addvalue_sz(ctr, val_name, sz);
2976 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
2977 uint32 dword)
2979 regval_ctr_delvalue(ctr, val_name);
2980 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2981 (char *) &dword, sizeof(dword));
2984 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
2985 bool b)
2987 uint8 bin_bool = (b ? 1 : 0);
2988 regval_ctr_delvalue(ctr, val_name);
2989 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2990 (char *) &bin_bool, sizeof(bin_bool));
2993 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
2994 const char *multi_sz)
2996 const char *a[2];
2998 a[0] = multi_sz;
2999 a[1] = NULL;
3001 regval_ctr_delvalue(ctr, val_name);
3002 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3005 /****************************************************************************
3006 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3008 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3009 * @return bool indicating success or failure
3010 ***************************************************************************/
3012 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3014 struct regval_ctr *ctr = NULL;
3015 fstring longname;
3016 const char *dnssuffix;
3017 char *allocated_string = NULL;
3018 const char *ascii_str;
3019 int i;
3021 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3022 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3023 ctr = info2->data->keys[i].values;
3025 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3026 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3028 /* we make the assumption that the netbios name is the same
3029 as the DNS name sinc ethe former will be what we used to
3030 join the domain */
3032 dnssuffix = get_mydnsdomname(talloc_tos());
3033 if (dnssuffix && *dnssuffix) {
3034 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3035 } else {
3036 fstrcpy( longname, global_myname() );
3039 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3041 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3042 return false;
3044 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3045 SAFE_FREE(allocated_string);
3047 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3048 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3049 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3050 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3051 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3052 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3053 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3054 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3055 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3057 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3058 (info2->attributes &
3059 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3061 switch (info2->attributes & 0x3) {
3062 case 0:
3063 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3064 break;
3065 case 1:
3066 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3067 break;
3068 case 2:
3069 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3070 break;
3071 default:
3072 ascii_str = "unknown";
3074 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3076 return True;
3079 /*****************************************************************
3080 ****************************************************************/
3082 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3083 struct GUID guid)
3085 int i;
3086 struct regval_ctr *ctr=NULL;
3088 /* find the DsSpooler key */
3089 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3090 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3091 ctr = info2->data->keys[i].values;
3093 regval_ctr_delvalue(ctr, "objectGUID");
3095 /* We used to store this as a REG_BINARY but that causes
3096 Vista to whine */
3098 regval_ctr_addvalue_sz(ctr, "objectGUID",
3099 GUID_string(talloc_tos(), &guid));
3102 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3103 NT_PRINTER_INFO_LEVEL *printer)
3105 ADS_STATUS ads_rc;
3106 LDAPMessage *res;
3107 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3108 char *srv_dn_utf8, **srv_cn_utf8;
3109 TALLOC_CTX *ctx;
3110 ADS_MODLIST mods;
3111 const char *attrs[] = {"objectGUID", NULL};
3112 struct GUID guid;
3113 WERROR win_rc = WERR_OK;
3114 size_t converted_size;
3116 /* build the ads mods */
3117 ctx = talloc_init("nt_printer_publish_ads");
3118 if (ctx == NULL) {
3119 return WERR_NOMEM;
3122 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3124 /* figure out where to publish */
3125 ads_find_machine_acct(ads, &res, global_myname());
3127 /* We use ldap_get_dn here as we need the answer
3128 * in utf8 to call ldap_explode_dn(). JRA. */
3130 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3131 if (!srv_dn_utf8) {
3132 TALLOC_FREE(ctx);
3133 return WERR_SERVER_UNAVAILABLE;
3135 ads_msgfree(ads, res);
3136 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3137 if (!srv_cn_utf8) {
3138 TALLOC_FREE(ctx);
3139 ldap_memfree(srv_dn_utf8);
3140 return WERR_SERVER_UNAVAILABLE;
3142 /* Now convert to CH_UNIX. */
3143 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3144 TALLOC_FREE(ctx);
3145 ldap_memfree(srv_dn_utf8);
3146 ldap_memfree(srv_cn_utf8);
3147 return WERR_SERVER_UNAVAILABLE;
3149 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3150 TALLOC_FREE(ctx);
3151 ldap_memfree(srv_dn_utf8);
3152 ldap_memfree(srv_cn_utf8);
3153 TALLOC_FREE(srv_dn);
3154 return WERR_SERVER_UNAVAILABLE;
3157 ldap_memfree(srv_dn_utf8);
3158 ldap_memfree(srv_cn_utf8);
3160 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3161 if (!srv_cn_escaped) {
3162 TALLOC_FREE(ctx);
3163 return WERR_SERVER_UNAVAILABLE;
3165 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3166 if (!sharename_escaped) {
3167 SAFE_FREE(srv_cn_escaped);
3168 TALLOC_FREE(ctx);
3169 return WERR_SERVER_UNAVAILABLE;
3172 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3174 SAFE_FREE(srv_cn_escaped);
3175 SAFE_FREE(sharename_escaped);
3177 mods = ads_init_mods(ctx);
3179 if (mods == NULL) {
3180 SAFE_FREE(prt_dn);
3181 TALLOC_FREE(ctx);
3182 return WERR_NOMEM;
3185 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3186 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3187 printer->info_2->sharename);
3189 /* publish it */
3190 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3191 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3192 int i;
3193 for (i=0; mods[i] != 0; i++)
3195 mods[i] = (LDAPMod *)-1;
3196 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3199 if (!ADS_ERR_OK(ads_rc))
3200 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3202 /* retreive the guid and store it locally */
3203 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3204 ZERO_STRUCT(guid);
3205 ads_pull_guid(ads, res, &guid);
3206 ads_msgfree(ads, res);
3207 store_printer_guid(printer->info_2, guid);
3208 win_rc = mod_a_printer(printer, 2);
3210 TALLOC_FREE(ctx);
3212 return win_rc;
3215 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3216 NT_PRINTER_INFO_LEVEL *printer)
3218 ADS_STATUS ads_rc;
3219 LDAPMessage *res = NULL;
3220 char *prt_dn = NULL;
3222 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3224 /* remove the printer from the directory */
3225 ads_rc = ads_find_printer_on_server(ads, &res,
3226 printer->info_2->sharename, global_myname());
3228 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3229 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3230 if (!prt_dn) {
3231 ads_msgfree(ads, res);
3232 return WERR_NOMEM;
3234 ads_rc = ads_del_dn(ads, prt_dn);
3235 TALLOC_FREE(prt_dn);
3238 if (res) {
3239 ads_msgfree(ads, res);
3241 return WERR_OK;
3244 /****************************************************************************
3245 * Publish a printer in the directory
3247 * @param snum describing printer service
3248 * @return WERROR indicating status of publishing
3249 ***************************************************************************/
3251 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3253 ADS_STATUS ads_rc;
3254 ADS_STRUCT *ads = NULL;
3255 NT_PRINTER_INFO_LEVEL *printer = NULL;
3256 WERROR win_rc;
3258 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3259 if (!W_ERROR_IS_OK(win_rc))
3260 goto done;
3262 switch (action) {
3263 case DSPRINT_PUBLISH:
3264 case DSPRINT_UPDATE:
3265 /* set the DsSpooler info and attributes */
3266 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3267 win_rc = WERR_NOMEM;
3268 goto done;
3271 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3272 break;
3273 case DSPRINT_UNPUBLISH:
3274 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3275 break;
3276 default:
3277 win_rc = WERR_NOT_SUPPORTED;
3278 goto done;
3281 win_rc = mod_a_printer(printer, 2);
3282 if (!W_ERROR_IS_OK(win_rc)) {
3283 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3284 goto done;
3287 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3288 if (!ads) {
3289 DEBUG(3, ("ads_init() failed\n"));
3290 win_rc = WERR_SERVER_UNAVAILABLE;
3291 goto done;
3293 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3294 SAFE_FREE(ads->auth.password);
3295 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3296 NULL, NULL);
3298 /* ads_connect() will find the DC for us */
3299 ads_rc = ads_connect(ads);
3300 if (!ADS_ERR_OK(ads_rc)) {
3301 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3302 win_rc = WERR_ACCESS_DENIED;
3303 goto done;
3306 switch (action) {
3307 case DSPRINT_PUBLISH:
3308 case DSPRINT_UPDATE:
3309 win_rc = nt_printer_publish_ads(ads, printer);
3310 break;
3311 case DSPRINT_UNPUBLISH:
3312 win_rc = nt_printer_unpublish_ads(ads, printer);
3313 break;
3316 done:
3317 free_a_printer(&printer, 2);
3318 ads_destroy(&ads);
3319 return win_rc;
3322 WERROR check_published_printers(void)
3324 ADS_STATUS ads_rc;
3325 ADS_STRUCT *ads = NULL;
3326 int snum;
3327 int n_services = lp_numservices();
3328 NT_PRINTER_INFO_LEVEL *printer = NULL;
3330 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3331 if (!ads) {
3332 DEBUG(3, ("ads_init() failed\n"));
3333 return WERR_SERVER_UNAVAILABLE;
3335 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3336 SAFE_FREE(ads->auth.password);
3337 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3338 NULL, NULL);
3340 /* ads_connect() will find the DC for us */
3341 ads_rc = ads_connect(ads);
3342 if (!ADS_ERR_OK(ads_rc)) {
3343 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3344 ads_destroy(&ads);
3345 ads_kdestroy("MEMORY:prtpub_cache");
3346 return WERR_ACCESS_DENIED;
3349 for (snum = 0; snum < n_services; snum++) {
3350 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3351 continue;
3353 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3354 lp_servicename(snum))) &&
3355 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3356 nt_printer_publish_ads(ads, printer);
3358 free_a_printer(&printer, 2);
3361 ads_destroy(&ads);
3362 ads_kdestroy("MEMORY:prtpub_cache");
3363 return WERR_OK;
3366 bool is_printer_published(Printer_entry *print_hnd, int snum,
3367 struct GUID *guid)
3369 NT_PRINTER_INFO_LEVEL *printer = NULL;
3370 struct regval_ctr *ctr;
3371 struct regval_blob *guid_val;
3372 WERROR win_rc;
3373 int i;
3374 bool ret = False;
3375 DATA_BLOB blob;
3377 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3379 if (!W_ERROR_IS_OK(win_rc) ||
3380 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3381 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3382 !(ctr = printer->info_2->data->keys[i].values) ||
3383 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3385 free_a_printer(&printer, 2);
3386 return False;
3389 /* fetching printer guids really ought to be a separate function. */
3391 if ( guid ) {
3392 char *guid_str;
3394 /* We used to store the guid as REG_BINARY, then swapped
3395 to REG_SZ for Vista compatibility so check for both */
3397 switch ( regval_type(guid_val) ){
3398 case REG_SZ:
3399 blob = data_blob_const(regval_data_p(guid_val),
3400 regval_size(guid_val));
3401 pull_reg_sz(talloc_tos(), &blob, (const char **)&guid_str);
3402 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3403 talloc_free(guid_str);
3404 break;
3405 case REG_BINARY:
3406 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3407 ret = False;
3408 break;
3410 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3411 break;
3412 default:
3413 DEBUG(0,("is_printer_published: GUID value stored as "
3414 "invaluid type (%d)\n", regval_type(guid_val) ));
3415 break;
3419 free_a_printer(&printer, 2);
3420 return ret;
3422 #else
3423 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3425 return WERR_OK;
3428 WERROR check_published_printers(void)
3430 return WERR_OK;
3433 bool is_printer_published(Printer_entry *print_hnd, int snum,
3434 struct GUID *guid)
3436 return False;
3438 #endif /* HAVE_ADS */
3440 /****************************************************************************
3441 ***************************************************************************/
3443 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3445 NT_PRINTER_DATA *data;
3446 int i;
3447 int removed_keys = 0;
3448 int empty_slot;
3450 data = p2->data;
3451 empty_slot = data->num_keys;
3453 if ( !key )
3454 return WERR_INVALID_PARAM;
3456 /* remove all keys */
3458 if ( !strlen(key) ) {
3460 TALLOC_FREE( data );
3462 p2->data = NULL;
3464 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3465 p2->printername ));
3467 return WERR_OK;
3470 /* remove a specific key (and all subkeys) */
3472 for ( i=0; i<data->num_keys; i++ ) {
3473 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3474 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3475 data->keys[i].name));
3477 TALLOC_FREE( data->keys[i].name );
3478 TALLOC_FREE( data->keys[i].values );
3480 /* mark the slot as empty */
3482 ZERO_STRUCTP( &data->keys[i] );
3486 /* find the first empty slot */
3488 for ( i=0; i<data->num_keys; i++ ) {
3489 if ( !data->keys[i].name ) {
3490 empty_slot = i;
3491 removed_keys++;
3492 break;
3496 if ( i == data->num_keys )
3497 /* nothing was removed */
3498 return WERR_INVALID_PARAM;
3500 /* move everything down */
3502 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3503 if ( data->keys[i].name ) {
3504 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3505 ZERO_STRUCTP( &data->keys[i] );
3506 empty_slot++;
3507 removed_keys++;
3511 /* update count */
3513 data->num_keys -= removed_keys;
3515 /* sanity check to see if anything is left */
3517 if ( !data->num_keys ) {
3518 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3520 SAFE_FREE( data->keys );
3521 ZERO_STRUCTP( data );
3524 return WERR_OK;
3527 /****************************************************************************
3528 ***************************************************************************/
3530 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3532 WERROR result = WERR_OK;
3533 int key_index;
3535 /* we must have names on non-zero length */
3537 if ( !key || !*key|| !value || !*value )
3538 return WERR_INVALID_NAME;
3540 /* find the printer key first */
3542 key_index = lookup_printerkey( p2->data, key );
3543 if ( key_index == -1 )
3544 return WERR_OK;
3546 /* make sure the value exists so we can return the correct error code */
3548 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3549 return WERR_BADFILE;
3551 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3553 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3554 key, value ));
3556 return result;
3559 /****************************************************************************
3560 ***************************************************************************/
3562 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3563 uint32 type, uint8 *data, int real_len )
3565 WERROR result = WERR_OK;
3566 int key_index;
3568 /* we must have names on non-zero length */
3570 if ( !key || !*key|| !value || !*value )
3571 return WERR_INVALID_NAME;
3573 /* find the printer key first */
3575 key_index = lookup_printerkey( p2->data, key );
3576 if ( key_index == -1 )
3577 key_index = add_new_printer_key( p2->data, key );
3579 if ( key_index == -1 )
3580 return WERR_NOMEM;
3582 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3583 type, (const char *)data, real_len );
3585 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3586 key, value, type, real_len ));
3588 return result;
3591 /****************************************************************************
3592 ***************************************************************************/
3594 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3596 int key_index;
3598 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3599 return NULL;
3601 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3602 key, value ));
3604 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3607 /****************************************************************************
3608 Unpack a list of registry values frem the TDB
3609 ***************************************************************************/
3611 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3613 int len = 0;
3614 uint32 type;
3615 fstring string;
3616 const char *valuename = NULL;
3617 const char *keyname = NULL;
3618 char *str;
3619 int size;
3620 uint8 *data_p;
3621 struct regval_blob *regval_p;
3622 int key_index;
3624 /* add the "PrinterDriverData" key first for performance reasons */
3626 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3628 /* loop and unpack the rest of the registry values */
3630 while ( True ) {
3632 /* check to see if there are any more registry values */
3634 regval_p = NULL;
3635 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3636 if ( !regval_p )
3637 break;
3639 /* unpack the next regval */
3641 len += tdb_unpack(buf+len, buflen-len, "fdB",
3642 string,
3643 &type,
3644 &size,
3645 &data_p);
3647 /* lookup for subkey names which have a type of REG_NONE */
3648 /* there's no data with this entry */
3650 if ( type == REG_NONE ) {
3651 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3652 add_new_printer_key( printer_data, string );
3653 continue;
3657 * break of the keyname from the value name.
3658 * Valuenames can have embedded '\'s so be careful.
3659 * only support one level of keys. See the
3660 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3661 * -- jerry
3664 str = strchr_m( string, '\\');
3666 /* Put in "PrinterDriverData" is no key specified */
3668 if ( !str ) {
3669 keyname = SPOOL_PRINTERDATA_KEY;
3670 valuename = string;
3672 else {
3673 *str = '\0';
3674 keyname = string;
3675 valuename = str+1;
3678 /* see if we need a new key */
3680 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3681 key_index = add_new_printer_key( printer_data, keyname );
3683 if ( key_index == -1 ) {
3684 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3685 keyname));
3686 break;
3689 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3691 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3692 Thanks to Martin Zielinski for the hint. */
3694 if ( type == REG_BINARY &&
3695 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3696 strequal( valuename, "objectGUID" ) )
3698 struct GUID guid;
3700 /* convert the GUID to a UNICODE string */
3702 memcpy( &guid, data_p, sizeof(struct GUID) );
3704 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3705 valuename,
3706 GUID_string(talloc_tos(), &guid));
3708 } else {
3709 /* add the value */
3711 regval_ctr_addvalue( printer_data->keys[key_index].values,
3712 valuename, type, (const char *)data_p,
3713 size );
3716 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3720 return len;
3723 /****************************************************************************
3724 ***************************************************************************/
3726 static char *last_from;
3727 static char *last_to;
3729 static const char *get_last_from(void)
3731 if (!last_from) {
3732 return "";
3734 return last_from;
3737 static const char *get_last_to(void)
3739 if (!last_to) {
3740 return "";
3742 return last_to;
3745 static bool set_last_from_to(const char *from, const char *to)
3747 char *orig_from = last_from;
3748 char *orig_to = last_to;
3750 last_from = SMB_STRDUP(from);
3751 last_to = SMB_STRDUP(to);
3753 SAFE_FREE(orig_from);
3754 SAFE_FREE(orig_to);
3756 if (!last_from || !last_to) {
3757 SAFE_FREE(last_from);
3758 SAFE_FREE(last_to);
3759 return false;
3761 return true;
3764 static void map_to_os2_driver(fstring drivername)
3766 char *mapfile = lp_os2_driver_map();
3767 char **lines = NULL;
3768 int numlines = 0;
3769 int i;
3771 if (!strlen(drivername))
3772 return;
3774 if (!*mapfile)
3775 return;
3777 if (strequal(drivername,get_last_from())) {
3778 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3779 drivername,get_last_to()));
3780 fstrcpy(drivername,get_last_to());
3781 return;
3784 lines = file_lines_load(mapfile, &numlines,0,NULL);
3785 if (numlines == 0 || lines == NULL) {
3786 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3787 TALLOC_FREE(lines);
3788 return;
3791 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3793 for( i = 0; i < numlines; i++) {
3794 char *nt_name = lines[i];
3795 char *os2_name = strchr(nt_name,'=');
3797 if (!os2_name)
3798 continue;
3800 *os2_name++ = 0;
3802 while (isspace(*nt_name))
3803 nt_name++;
3805 if (!*nt_name || strchr("#;",*nt_name))
3806 continue;
3809 int l = strlen(nt_name);
3810 while (l && isspace(nt_name[l-1])) {
3811 nt_name[l-1] = 0;
3812 l--;
3816 while (isspace(*os2_name))
3817 os2_name++;
3820 int l = strlen(os2_name);
3821 while (l && isspace(os2_name[l-1])) {
3822 os2_name[l-1] = 0;
3823 l--;
3827 if (strequal(nt_name,drivername)) {
3828 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3829 set_last_from_to(drivername,os2_name);
3830 fstrcpy(drivername,os2_name);
3831 TALLOC_FREE(lines);
3832 return;
3836 TALLOC_FREE(lines);
3839 /****************************************************************************
3840 Get a default printer info 2 struct.
3841 ****************************************************************************/
3843 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3844 const char *servername,
3845 const char* sharename,
3846 bool get_loc_com)
3848 int snum = lp_servicenumber(sharename);
3850 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3851 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3852 servername, sharename);
3853 fstrcpy(info->sharename, sharename);
3854 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3856 /* by setting the driver name to an empty string, a local NT admin
3857 can now run the **local** APW to install a local printer driver
3858 for a Samba shared printer in 2.2. Without this, drivers **must** be
3859 installed on the Samba server for NT clients --jerry */
3860 #if 0 /* JERRY --do not uncomment-- */
3861 if (!*info->drivername)
3862 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3863 #endif
3866 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3868 strlcpy(info->comment, "", sizeof(info->comment));
3869 fstrcpy(info->printprocessor, "winprint");
3870 fstrcpy(info->datatype, "RAW");
3872 #ifdef HAVE_CUPS
3873 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3874 /* Pull the location and comment strings from cups if we don't
3875 already have one */
3876 if ( !strlen(info->location) || !strlen(info->comment) )
3877 cups_pull_comment_location( info );
3879 #endif
3881 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3883 info->starttime = 0; /* Minutes since 12:00am GMT */
3884 info->untiltime = 0; /* Minutes since 12:00am GMT */
3885 info->priority = 1;
3886 info->default_priority = 1;
3887 info->setuptime = (uint32)time(NULL);
3890 * I changed this as I think it is better to have a generic
3891 * DEVMODE than to crash Win2k explorer.exe --jerry
3892 * See the HP Deskjet 990c Win2k drivers for an example.
3894 * However the default devmode appears to cause problems
3895 * with the HP CLJ 8500 PCL driver. Hence the addition of
3896 * the "default devmode" parameter --jerry 22/01/2002
3899 if (lp_default_devmode(snum)) {
3900 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3901 goto fail;
3903 } else {
3904 info->devmode = NULL;
3907 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3908 goto fail;
3911 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
3912 if (!info->data) {
3913 goto fail;
3916 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
3918 return WERR_OK;
3920 fail:
3921 if (info->devmode)
3922 free_nt_devicemode(&info->devmode);
3924 return WERR_ACCESS_DENIED;
3927 /****************************************************************************
3928 ****************************************************************************/
3930 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
3931 const char *servername,
3932 const char *sharename,
3933 bool get_loc_com)
3935 int len = 0;
3936 int snum = lp_servicenumber(sharename);
3937 TDB_DATA kbuf, dbuf;
3938 fstring printername;
3939 char adevice[MAXDEVICENAME];
3940 char *comment = NULL;
3942 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
3944 dbuf = tdb_fetch(tdb_printers, kbuf);
3945 if (!dbuf.dptr) {
3946 return get_a_printer_2_default(info, servername,
3947 sharename, get_loc_com);
3950 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3951 &info->attributes,
3952 &info->priority,
3953 &info->default_priority,
3954 &info->starttime,
3955 &info->untiltime,
3956 &info->status,
3957 &info->cjobs,
3958 &info->averageppm,
3959 &info->changeid,
3960 &info->c_setprinter,
3961 &info->setuptime,
3962 info->servername,
3963 info->printername,
3964 info->sharename,
3965 info->portname,
3966 info->drivername,
3967 &comment,
3968 info->location,
3969 info->sepfile,
3970 info->printprocessor,
3971 info->datatype,
3972 info->parameters);
3974 if (comment) {
3975 strlcpy(info->comment, comment, sizeof(info->comment));
3976 SAFE_FREE(comment);
3979 /* Samba has to have shared raw drivers. */
3980 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3981 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3983 /* Restore the stripped strings. */
3984 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3986 if ( lp_force_printername(snum) ) {
3987 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3988 } else {
3989 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3992 fstrcpy(info->printername, printername);
3994 #ifdef HAVE_CUPS
3995 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3996 /* Pull the location and comment strings from cups if we don't
3997 already have one */
3998 if ( !strlen(info->location) || !strlen(info->comment) )
3999 cups_pull_comment_location( info );
4001 #endif
4003 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4006 * Some client drivers freak out if there is a NULL devmode
4007 * (probably the driver is not checking before accessing
4008 * the devmode pointer) --jerry
4010 * See comments in get_a_printer_2_default()
4013 if (lp_default_devmode(snum) && !info->devmode) {
4014 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4015 printername));
4016 info->devmode = construct_nt_devicemode(printername);
4019 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4020 if (info->devmode) {
4021 fstrcpy(info->devmode->devicename, adevice);
4024 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4025 DEBUG(0,("unpack_values: talloc() failed!\n"));
4026 SAFE_FREE(dbuf.dptr);
4027 return WERR_NOMEM;
4029 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4031 /* This will get the current RPC talloc context, but we should be
4032 passing this as a parameter... fixme... JRA ! */
4034 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4035 SAFE_FREE(dbuf.dptr);
4036 return WERR_NOMEM;
4039 /* Fix for OS/2 drivers. */
4041 if (get_remote_arch() == RA_OS2) {
4042 map_to_os2_driver(info->drivername);
4045 SAFE_FREE(dbuf.dptr);
4047 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4048 sharename, info->printername, info->drivername));
4050 return WERR_OK;
4053 /****************************************************************************
4054 Debugging function, dump at level 6 the struct in the logs.
4055 ****************************************************************************/
4056 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4058 uint32 result;
4059 NT_PRINTER_INFO_LEVEL_2 *info2;
4061 DEBUG(106,("Dumping printer at level [%d]\n", level));
4063 switch (level) {
4064 case 2:
4066 if (printer->info_2 == NULL)
4067 result=5;
4068 else
4070 info2=printer->info_2;
4072 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4073 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4074 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4075 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4076 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4077 DEBUGADD(106,("status:[%d]\n", info2->status));
4078 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4079 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4080 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4081 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4082 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4084 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4085 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4086 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4087 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4088 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4089 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4090 DEBUGADD(106,("location:[%s]\n", info2->location));
4091 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4092 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4093 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4094 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4095 result=0;
4097 break;
4099 default:
4100 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4101 result=1;
4102 break;
4105 return result;
4108 /****************************************************************************
4109 Update the changeid time.
4110 This is SO NASTY as some drivers need this to change, others need it
4111 static. This value will change every second, and I must hope that this
4112 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4113 UTAH ! JRA.
4114 ****************************************************************************/
4116 static uint32 rev_changeid(void)
4118 struct timeval tv;
4120 get_process_uptime(&tv);
4122 #if 1 /* JERRY */
4123 /* Return changeid as msec since spooler restart */
4124 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4125 #else
4127 * This setting seems to work well but is too untested
4128 * to replace the above calculation. Left in for experiementation
4129 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4131 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4132 #endif
4137 * The function below are the high level ones.
4138 * only those ones must be called from the spoolss code.
4139 * JFM.
4142 /****************************************************************************
4143 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4144 ****************************************************************************/
4146 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4148 WERROR result;
4150 dump_a_printer(printer, level);
4152 switch (level) {
4153 case 2:
4156 * Update the changestamp. Emperical tests show that the
4157 * ChangeID is always updated,but c_setprinter is
4158 * global spooler variable (not per printer).
4161 /* ChangeID **must** be increasing over the lifetime
4162 of client's spoolss service in order for the
4163 client's cache to show updates */
4165 printer->info_2->changeid = rev_changeid();
4168 * Because one day someone will ask:
4169 * NT->NT An admin connection to a remote
4170 * printer show changes imeediately in
4171 * the properities dialog
4173 * A non-admin connection will only show the
4174 * changes after viewing the properites page
4175 * 2 times. Seems to be related to a
4176 * race condition in the client between the spooler
4177 * updating the local cache and the Explorer.exe GUI
4178 * actually displaying the properties.
4180 * This is fixed in Win2k. admin/non-admin
4181 * connections both display changes immediately.
4183 * 14/12/01 --jerry
4186 result=update_a_printer_2(printer->info_2);
4187 break;
4189 default:
4190 result=WERR_UNKNOWN_LEVEL;
4191 break;
4194 return result;
4197 /****************************************************************************
4198 Initialize printer devmode & data with previously saved driver init values.
4199 ****************************************************************************/
4201 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4203 int len = 0;
4204 char *key = NULL;
4205 TDB_DATA dbuf;
4206 NT_PRINTER_INFO_LEVEL_2 info;
4209 ZERO_STRUCT(info);
4212 * Delete any printer data 'values' already set. When called for driver
4213 * replace, there will generally be some, but during an add printer, there
4214 * should not be any (if there are delete them).
4217 if ( info_ptr->data )
4218 delete_all_printer_data( info_ptr, "" );
4220 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4221 info_ptr->drivername) < 0) {
4222 return false;
4225 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4226 if (!dbuf.dptr) {
4228 * When changing to a driver that has no init info in the tdb, remove
4229 * the previous drivers init info and leave the new on blank.
4231 free_nt_devicemode(&info_ptr->devmode);
4232 SAFE_FREE(key);
4233 return false;
4236 SAFE_FREE(key);
4238 * Get the saved DEVMODE..
4241 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4244 * The saved DEVMODE contains the devicename from the printer used during
4245 * the initialization save. Change it to reflect the new printer.
4248 if ( info.devmode ) {
4249 ZERO_STRUCT(info.devmode->devicename);
4250 fstrcpy(info.devmode->devicename, info_ptr->printername);
4254 * NT/2k does not change out the entire DeviceMode of a printer
4255 * when changing the driver. Only the driverextra, private, &
4256 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4258 * Later examination revealed that Windows NT/2k does reset the
4259 * the printer's device mode, bit **only** when you change a
4260 * property of the device mode such as the page orientation.
4261 * --jerry
4265 /* Bind the saved DEVMODE to the new the printer */
4267 free_nt_devicemode(&info_ptr->devmode);
4268 info_ptr->devmode = info.devmode;
4270 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4271 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4273 /* Add the printer data 'values' to the new printer */
4275 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4276 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4277 return False;
4280 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4282 SAFE_FREE(dbuf.dptr);
4284 return true;
4287 /****************************************************************************
4288 Initialize printer devmode & data with previously saved driver init values.
4289 When a printer is created using AddPrinter, the drivername bound to the
4290 printer is used to lookup previously saved driver initialization info, which
4291 is bound to the new printer.
4292 ****************************************************************************/
4294 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4296 bool result = False;
4298 switch (level) {
4299 case 2:
4300 result = set_driver_init_2(printer->info_2);
4301 break;
4303 default:
4304 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4305 level));
4306 break;
4309 return result;
4312 /****************************************************************************
4313 Delete driver init data stored for a specified driver
4314 ****************************************************************************/
4316 bool del_driver_init(const char *drivername)
4318 char *key;
4319 bool ret;
4321 if (!drivername || !*drivername) {
4322 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4323 return false;
4326 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4327 return false;
4330 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4331 drivername));
4333 ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4334 SAFE_FREE(key);
4335 return ret;
4338 /****************************************************************************
4339 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4340 in the tdb. Note: this is different from the driver entry and the printer
4341 entry. There should be a single driver init entry for each driver regardless
4342 of whether it was installed from NT or 2K. Technically, they should be
4343 different, but they work out to the same struct.
4344 ****************************************************************************/
4346 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4348 char *key = NULL;
4349 uint8 *buf;
4350 int buflen, len, ret;
4351 int retlen;
4352 TDB_DATA dbuf;
4354 buf = NULL;
4355 buflen = 0;
4357 again:
4358 len = 0;
4359 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4361 retlen = pack_values( info->data, buf+len, buflen-len );
4362 if (retlen == -1) {
4363 ret = -1;
4364 goto done;
4366 len += retlen;
4368 if (buflen < len) {
4369 buf = (uint8 *)SMB_REALLOC(buf, len);
4370 if (!buf) {
4371 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4372 ret = -1;
4373 goto done;
4375 buflen = len;
4376 goto again;
4379 SAFE_FREE(key);
4380 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4381 ret = (uint32)-1;
4382 goto done;
4385 dbuf.dptr = buf;
4386 dbuf.dsize = len;
4388 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4390 done:
4391 if (ret == -1)
4392 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4394 SAFE_FREE(buf);
4396 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4397 info->sharename, info->drivername));
4399 return ret;
4402 /****************************************************************************
4403 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4404 ****************************************************************************/
4406 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4408 uint32 result;
4410 dump_a_printer(printer, level);
4412 switch (level) {
4413 case 2:
4414 result = update_driver_init_2(printer->info_2);
4415 break;
4416 default:
4417 result = 1;
4418 break;
4421 return result;
4424 /****************************************************************************
4425 Convert the printer data value, a REG_BINARY array, into an initialization
4426 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4427 got to keep the endians happy :).
4428 ****************************************************************************/
4430 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4431 const uint8_t *data, uint32_t data_len)
4433 struct spoolss_DeviceMode devmode;
4434 enum ndr_err_code ndr_err;
4435 DATA_BLOB blob;
4437 ZERO_STRUCT(devmode);
4439 blob = data_blob_const(data, data_len);
4441 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4442 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4443 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4444 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4445 return false;
4448 return convert_devicemode("", &devmode, &nt_devmode);
4451 /****************************************************************************
4452 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4454 1. Use the driver's config DLL to this UNC printername and:
4455 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4456 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4457 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4459 The last step triggers saving the "driver initialization" information for
4460 this printer into the tdb. Later, new printers that use this driver will
4461 have this initialization information bound to them. This simulates the
4462 driver initialization, as if it had run on the Samba server (as it would
4463 have done on NT).
4465 The Win32 client side code requirement sucks! But until we can run arbitrary
4466 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4468 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4469 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4470 about it and you will realize why. JRR 010720
4471 ****************************************************************************/
4473 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4475 WERROR status = WERR_OK;
4476 TALLOC_CTX *ctx = NULL;
4477 NT_DEVICEMODE *nt_devmode = NULL;
4478 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4481 * When the DEVMODE is already set on the printer, don't try to unpack it.
4483 DEBUG(8,("save_driver_init_2: Enter...\n"));
4485 if ( !printer->info_2->devmode && data_len ) {
4487 * Set devmode on printer info, so entire printer initialization can be
4488 * saved to tdb.
4491 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4492 return WERR_NOMEM;
4494 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4495 status = WERR_NOMEM;
4496 goto done;
4499 ZERO_STRUCTP(nt_devmode);
4502 * The DEVMODE is held in the 'data' component of the param in raw binary.
4503 * Convert it to to a devmode structure
4505 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4506 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4507 status = WERR_INVALID_PARAM;
4508 goto done;
4511 printer->info_2->devmode = nt_devmode;
4515 * Pack up and add (or update) the DEVMODE and any current printer data to
4516 * a 'driver init' element in the tdb
4520 if ( update_driver_init(printer, 2) != 0 ) {
4521 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4522 status = WERR_NOMEM;
4523 goto done;
4527 * If driver initialization info was successfully saved, set the current
4528 * printer to match it. This allows initialization of the current printer
4529 * as well as the driver.
4531 status = mod_a_printer(printer, 2);
4532 if (!W_ERROR_IS_OK(status)) {
4533 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4534 printer->info_2->printername));
4537 done:
4538 talloc_destroy(ctx);
4539 free_nt_devicemode( &nt_devmode );
4541 printer->info_2->devmode = tmp_devmode;
4543 return status;
4546 /****************************************************************************
4547 Update the driver init info (DEVMODE and specifics) for a printer
4548 ****************************************************************************/
4550 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4552 WERROR status = WERR_OK;
4554 switch (level) {
4555 case 2:
4556 status = save_driver_init_2( printer, data, data_len );
4557 break;
4558 default:
4559 status = WERR_UNKNOWN_LEVEL;
4560 break;
4563 return status;
4566 /****************************************************************************
4567 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4569 Previously the code had a memory allocation problem because it always
4570 used the TALLOC_CTX from the Printer_entry*. This context lasts
4571 as a long as the original handle is open. So if the client made a lot
4572 of getprinter[data]() calls, the memory usage would climb. Now we use
4573 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4574 still use the Printer_entry->ctx for maintaining the cache copy though
4575 since that object must live as long as the handle by definition.
4576 --jerry
4578 ****************************************************************************/
4580 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4581 const char *sharename, bool get_loc_com)
4583 WERROR result;
4584 fstring servername;
4586 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4588 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4589 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4590 return WERR_NOMEM;
4593 switch (level) {
4594 case 2:
4595 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4596 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4597 TALLOC_FREE( *pp_printer );
4598 return WERR_NOMEM;
4601 if ( print_hnd )
4602 fstrcpy( servername, print_hnd->servername );
4603 else {
4604 fstrcpy( servername, "%L" );
4605 standard_sub_basic( "", "", servername,
4606 sizeof(servername)-1 );
4609 result = get_a_printer_2( (*pp_printer)->info_2,
4610 servername, sharename, get_loc_com);
4612 /* we have a new printer now. Save it with this handle */
4614 if ( !W_ERROR_IS_OK(result) ) {
4615 TALLOC_FREE( *pp_printer );
4616 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4617 sharename, (unsigned int)level, win_errstr(result)));
4618 return result;
4621 dump_a_printer( *pp_printer, level);
4623 break;
4625 default:
4626 TALLOC_FREE( *pp_printer );
4627 return WERR_UNKNOWN_LEVEL;
4630 return WERR_OK;
4633 WERROR get_a_printer( Printer_entry *print_hnd,
4634 NT_PRINTER_INFO_LEVEL **pp_printer,
4635 uint32 level,
4636 const char *sharename)
4638 return get_a_printer_internal(print_hnd, pp_printer, level,
4639 sharename, true);
4642 WERROR get_a_printer_search( Printer_entry *print_hnd,
4643 NT_PRINTER_INFO_LEVEL **pp_printer,
4644 uint32 level,
4645 const char *sharename)
4647 return get_a_printer_internal(print_hnd, pp_printer, level,
4648 sharename, false);
4651 /****************************************************************************
4652 Deletes a NT_PRINTER_INFO_LEVEL struct.
4653 ****************************************************************************/
4655 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4657 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4659 if ( !printer )
4660 return 0;
4662 switch (level) {
4663 case 2:
4664 if ( printer->info_2 )
4665 free_nt_printer_info_level_2(&printer->info_2);
4666 break;
4668 default:
4669 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4670 return 1;
4673 TALLOC_FREE(*pp_printer);
4675 return 0;
4678 /****************************************************************************
4679 ****************************************************************************/
4681 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4682 struct spoolss_AddDriverInfoCtr *r,
4683 char **driver_name,
4684 uint32_t *version)
4686 struct spoolss_DriverInfo8 info8;
4688 ZERO_STRUCT(info8);
4690 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4692 switch (r->level) {
4693 case 3:
4694 info8.version = r->info.info3->version;
4695 info8.driver_name = r->info.info3->driver_name;
4696 info8.architecture = r->info.info3->architecture;
4697 info8.driver_path = r->info.info3->driver_path;
4698 info8.data_file = r->info.info3->data_file;
4699 info8.config_file = r->info.info3->config_file;
4700 info8.help_file = r->info.info3->help_file;
4701 info8.monitor_name = r->info.info3->monitor_name;
4702 info8.default_datatype = r->info.info3->default_datatype;
4703 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4704 info8.dependent_files = r->info.info3->dependent_files->string;
4706 break;
4707 case 6:
4708 info8.version = r->info.info6->version;
4709 info8.driver_name = r->info.info6->driver_name;
4710 info8.architecture = r->info.info6->architecture;
4711 info8.driver_path = r->info.info6->driver_path;
4712 info8.data_file = r->info.info6->data_file;
4713 info8.config_file = r->info.info6->config_file;
4714 info8.help_file = r->info.info6->help_file;
4715 info8.monitor_name = r->info.info6->monitor_name;
4716 info8.default_datatype = r->info.info6->default_datatype;
4717 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4718 info8.dependent_files = r->info.info6->dependent_files->string;
4720 info8.driver_date = r->info.info6->driver_date;
4721 info8.driver_version = r->info.info6->driver_version;
4722 info8.manufacturer_name = r->info.info6->manufacturer_name;
4723 info8.manufacturer_url = r->info.info6->manufacturer_url;
4724 info8.hardware_id = r->info.info6->hardware_id;
4725 info8.provider = r->info.info6->provider;
4726 break;
4727 case 8:
4728 info8.version = r->info.info8->version;
4729 info8.driver_name = r->info.info8->driver_name;
4730 info8.architecture = r->info.info8->architecture;
4731 info8.driver_path = r->info.info8->driver_path;
4732 info8.data_file = r->info.info8->data_file;
4733 info8.config_file = r->info.info8->config_file;
4734 info8.help_file = r->info.info8->help_file;
4735 info8.monitor_name = r->info.info8->monitor_name;
4736 info8.default_datatype = r->info.info8->default_datatype;
4737 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4738 info8.dependent_files = r->info.info8->dependent_files->string;
4740 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4741 info8.previous_names = r->info.info8->previous_names->string;
4743 info8.driver_date = r->info.info8->driver_date;
4744 info8.driver_version = r->info.info8->driver_version;
4745 info8.manufacturer_name = r->info.info8->manufacturer_name;
4746 info8.manufacturer_url = r->info.info8->manufacturer_url;
4747 info8.hardware_id = r->info.info8->hardware_id;
4748 info8.provider = r->info.info8->provider;
4749 info8.print_processor = r->info.info8->print_processor;
4750 info8.vendor_setup = r->info.info8->vendor_setup;
4751 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4752 info8.color_profiles = r->info.info8->color_profiles->string;
4754 info8.inf_path = r->info.info8->inf_path;
4755 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4756 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4757 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4759 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4760 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4761 break;
4762 default:
4763 return -1;
4766 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4767 if (!*driver_name) {
4768 return -1;
4770 *version = info8.version;
4772 return add_a_printer_driver_8(&info8);
4775 /****************************************************************************
4776 ****************************************************************************/
4778 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4779 struct spoolss_DriverInfo8 **driver,
4780 const char *drivername, const char *architecture,
4781 uint32_t version)
4783 WERROR result;
4784 struct spoolss_DriverInfo3 info3;
4785 struct spoolss_DriverInfo8 *info8;
4787 ZERO_STRUCT(info3);
4789 /* Sometime we just want any version of the driver */
4791 if (version == DRIVER_ANY_VERSION) {
4792 /* look for Win2k first and then for NT4 */
4793 result = get_a_printer_driver_8(mem_ctx,
4794 driver,
4795 drivername,
4796 architecture, 3);
4797 if (!W_ERROR_IS_OK(result)) {
4798 result = get_a_printer_driver_8(mem_ctx,
4799 driver,
4800 drivername,
4801 architecture, 2);
4803 } else {
4804 result = get_a_printer_driver_8(mem_ctx,
4805 driver,
4806 drivername,
4807 architecture,
4808 version);
4811 if (W_ERROR_IS_OK(result)) {
4812 return WERR_OK;
4815 /* falling back to lookup for old level 3 driver - gd */
4817 /* Sometime we just want any version of the driver */
4819 if (version == DRIVER_ANY_VERSION) {
4820 /* look for Win2k first and then for NT4 */
4821 result = get_a_printer_driver_3(mem_ctx,
4822 &info3,
4823 drivername,
4824 architecture, 3);
4825 if (!W_ERROR_IS_OK(result)) {
4826 result = get_a_printer_driver_3(mem_ctx,
4827 &info3,
4828 drivername,
4829 architecture, 2);
4831 } else {
4832 result = get_a_printer_driver_3(mem_ctx,
4833 &info3,
4834 drivername,
4835 architecture,
4836 version);
4839 if (!W_ERROR_IS_OK(result)) {
4840 return result;
4843 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4844 if (!info8) {
4845 return WERR_NOMEM;
4848 info8->version = info3.version;
4849 info8->driver_name = info3.driver_name;
4850 info8->architecture = info3.architecture;
4851 info8->driver_path = info3.driver_path;
4852 info8->data_file = info3.data_file;
4853 info8->config_file = info3.config_file;
4854 info8->help_file = info3.help_file;
4855 info8->dependent_files = info3.dependent_files;
4856 info8->monitor_name = info3.monitor_name;
4857 info8->default_datatype = info3.default_datatype;
4859 *driver = info8;
4861 return WERR_OK;
4864 /****************************************************************************
4865 ****************************************************************************/
4867 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
4869 talloc_free(driver);
4870 return 0;
4874 /****************************************************************************
4875 Determine whether or not a particular driver is currently assigned
4876 to a printer
4877 ****************************************************************************/
4879 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
4881 int snum;
4882 int n_services = lp_numservices();
4883 NT_PRINTER_INFO_LEVEL *printer = NULL;
4884 bool in_use = False;
4886 if (!r) {
4887 return false;
4890 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4892 /* loop through the printers.tdb and check for the drivername */
4894 for (snum=0; snum<n_services && !in_use; snum++) {
4895 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4896 continue;
4898 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4899 continue;
4901 if (strequal(r->driver_name, printer->info_2->drivername))
4902 in_use = True;
4904 free_a_printer( &printer, 2 );
4907 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4909 if ( in_use ) {
4910 struct spoolss_DriverInfo8 *d;
4911 WERROR werr;
4913 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
4915 /* we can still remove the driver if there is one of
4916 "Windows NT x86" version 2 or 3 left */
4918 if (!strequal("Windows NT x86", r->architecture)) {
4919 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
4921 else {
4922 switch (r->version) {
4923 case 2:
4924 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
4925 break;
4926 case 3:
4927 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
4928 break;
4929 default:
4930 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4931 r->version));
4932 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4933 break;
4937 /* now check the error code */
4939 if ( W_ERROR_IS_OK(werr) ) {
4940 /* it's ok to remove the driver, we have other architctures left */
4941 in_use = False;
4942 free_a_printer_driver(d);
4946 /* report that the driver is not in use by default */
4948 return in_use;
4952 /**********************************************************************
4953 Check to see if a ogiven file is in use by *info
4954 *********************************************************************/
4956 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
4958 int i = 0;
4960 if ( !info )
4961 return False;
4963 /* mz: skip files that are in the list but already deleted */
4964 if (!file || !file[0]) {
4965 return false;
4968 if (strequal(file, info->driver_path))
4969 return True;
4971 if (strequal(file, info->data_file))
4972 return True;
4974 if (strequal(file, info->config_file))
4975 return True;
4977 if (strequal(file, info->help_file))
4978 return True;
4980 /* see of there are any dependent files to examine */
4982 if (!info->dependent_files)
4983 return False;
4985 while (info->dependent_files[i] && *info->dependent_files[i]) {
4986 if (strequal(file, info->dependent_files[i]))
4987 return True;
4988 i++;
4991 return False;
4995 /**********************************************************************
4996 Utility function to remove the dependent file pointed to by the
4997 input parameter from the list
4998 *********************************************************************/
5000 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
5003 /* bump everything down a slot */
5005 while (files && files[idx+1]) {
5006 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
5007 idx++;
5010 files[idx] = NULL;
5012 return;
5015 /**********************************************************************
5016 Check if any of the files used by src are also used by drv
5017 *********************************************************************/
5019 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
5020 struct spoolss_DriverInfo8 *src,
5021 const struct spoolss_DriverInfo8 *drv)
5023 bool in_use = False;
5024 int i = 0;
5026 if ( !src || !drv )
5027 return False;
5029 /* check each file. Remove it from the src structure if it overlaps */
5031 if (drv_file_in_use(src->driver_path, drv)) {
5032 in_use = True;
5033 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
5034 src->driver_path = talloc_strdup(mem_ctx, "");
5035 if (!src->driver_path) { return false; }
5038 if (drv_file_in_use(src->data_file, drv)) {
5039 in_use = True;
5040 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
5041 src->data_file = talloc_strdup(mem_ctx, "");
5042 if (!src->data_file) { return false; }
5045 if (drv_file_in_use(src->config_file, drv)) {
5046 in_use = True;
5047 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
5048 src->config_file = talloc_strdup(mem_ctx, "");
5049 if (!src->config_file) { return false; }
5052 if (drv_file_in_use(src->help_file, drv)) {
5053 in_use = True;
5054 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
5055 src->help_file = talloc_strdup(mem_ctx, "");
5056 if (!src->help_file) { return false; }
5059 /* are there any dependentfiles to examine? */
5061 if (!src->dependent_files)
5062 return in_use;
5064 while (src->dependent_files[i] && *src->dependent_files[i]) {
5065 if (drv_file_in_use(src->dependent_files[i], drv)) {
5066 in_use = True;
5067 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
5068 trim_dependent_file(mem_ctx, src->dependent_files, i);
5069 } else
5070 i++;
5073 return in_use;
5076 /****************************************************************************
5077 Determine whether or not a particular driver files are currently being
5078 used by any other driver.
5080 Return value is True if any files were in use by other drivers
5081 and False otherwise.
5083 Upon return, *info has been modified to only contain the driver files
5084 which are not in use
5086 Fix from mz:
5088 This needs to check all drivers to ensure that all files in use
5089 have been removed from *info, not just the ones in the first
5090 match.
5091 ****************************************************************************/
5093 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo8 *info)
5096 int i;
5097 int ndrivers;
5098 uint32 version;
5099 fstring *list = NULL;
5100 struct spoolss_DriverInfo8 *driver;
5101 bool in_use = false;
5103 if ( !info )
5104 return False;
5106 version = info->version;
5108 /* loop over all driver versions */
5110 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5112 /* get the list of drivers */
5114 list = NULL;
5115 ndrivers = get_ntdrivers(&list, info->architecture, version);
5117 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5118 ndrivers, info->architecture, version));
5120 /* check each driver for overlap in files */
5122 for (i=0; i<ndrivers; i++) {
5123 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5125 driver = NULL;
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
5128 SAFE_FREE(list);
5129 return True;
5132 /* check if d2 uses any files from d1 */
5133 /* only if this is a different driver than the one being deleted */
5135 if (!strequal(info->driver_name, driver->driver_name)) {
5136 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5137 /* mz: Do not instantly return -
5138 * we need to ensure this file isn't
5139 * also in use by other drivers. */
5140 in_use = true;
5144 free_a_printer_driver(driver);
5147 SAFE_FREE(list);
5149 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5151 return in_use;
5154 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5155 const char *name)
5157 struct smb_filename *smb_fname = NULL;
5158 NTSTATUS status;
5160 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5161 &smb_fname);
5162 if (!NT_STATUS_IS_OK(status)) {
5163 return status;
5166 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5168 TALLOC_FREE(smb_fname);
5169 return status;
5172 /****************************************************************************
5173 Actually delete the driver files. Make sure that
5174 printer_driver_files_in_use() return False before calling
5175 this.
5176 ****************************************************************************/
5178 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5179 const struct spoolss_DriverInfo8 *r)
5181 int i = 0;
5182 char *s;
5183 const char *file;
5184 connection_struct *conn;
5185 NTSTATUS nt_status;
5186 char *oldcwd;
5187 fstring printdollar;
5188 int printdollar_snum;
5189 bool ret = false;
5191 if (!r) {
5192 return false;
5195 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5196 r->driver_name, r->version));
5198 fstrcpy(printdollar, "print$");
5200 printdollar_snum = find_service(printdollar);
5201 if (printdollar_snum == -1) {
5202 return false;
5205 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5206 lp_pathname(printdollar_snum),
5207 rpc_pipe->server_info, &oldcwd);
5208 if (!NT_STATUS_IS_OK(nt_status)) {
5209 DEBUG(0,("delete_driver_files: create_conn_struct "
5210 "returned %s\n", nt_errstr(nt_status)));
5211 return false;
5214 if ( !CAN_WRITE(conn) ) {
5215 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5216 goto fail;
5219 /* now delete the files; must strip the '\print$' string from
5220 fron of path */
5222 if (r->driver_path && r->driver_path[0]) {
5223 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5224 file = s;
5225 DEBUG(10,("deleting driverfile [%s]\n", s));
5226 driver_unlink_internals(conn, file);
5230 if (r->config_file && r->config_file[0]) {
5231 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5232 file = s;
5233 DEBUG(10,("deleting configfile [%s]\n", s));
5234 driver_unlink_internals(conn, file);
5238 if (r->data_file && r->data_file[0]) {
5239 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5240 file = s;
5241 DEBUG(10,("deleting datafile [%s]\n", s));
5242 driver_unlink_internals(conn, file);
5246 if (r->help_file && r->help_file[0]) {
5247 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5248 file = s;
5249 DEBUG(10,("deleting helpfile [%s]\n", s));
5250 driver_unlink_internals(conn, file);
5254 /* check if we are done removing files */
5256 if (r->dependent_files) {
5257 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5258 char *p;
5260 /* bypass the "\print$" portion of the path */
5262 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5263 file = p;
5264 DEBUG(10,("deleting dependent file [%s]\n", file));
5265 driver_unlink_internals(conn, file);
5268 i++;
5272 goto done;
5273 fail:
5274 ret = false;
5275 done:
5276 if (conn != NULL) {
5277 vfs_ChDir(conn, oldcwd);
5278 conn_free(conn);
5280 return ret;
5283 /****************************************************************************
5284 Remove a printer driver from the TDB. This assumes that the the driver was
5285 previously looked up.
5286 ***************************************************************************/
5288 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5289 const struct spoolss_DriverInfo8 *r,
5290 uint32 version, bool delete_files )
5292 char *key = NULL;
5293 char *key8 = NULL;
5294 const char *arch;
5295 TDB_DATA dbuf;
5297 /* delete the tdb data first */
5299 arch = get_short_archi(r->architecture);
5300 if (!arch) {
5301 return WERR_UNKNOWN_PRINTER_DRIVER;
5304 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5305 arch, version, r->driver_name) < 0) {
5306 return WERR_NOMEM;
5308 if (asprintf(&key8, "%s%s/%d/%s", DRIVERS_PREFIX8,
5309 arch, version, r->driver_name) < 0) {
5310 SAFE_FREE(key);
5311 return WERR_NOMEM;
5314 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5315 key, delete_files ? "TRUE" : "FALSE" ));
5317 /* check if the driver actually exists for this environment */
5319 dbuf = tdb_fetch_bystring(tdb_drivers, key8);
5320 if (dbuf.dptr) {
5321 /* ok... the driver exists so the delete should return success */
5322 if (tdb_delete_bystring(tdb_drivers, key8) == -1) {
5323 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key8));
5324 SAFE_FREE(key);
5325 SAFE_FREE(key8);
5326 return WERR_ACCESS_DENIED;
5328 SAFE_FREE(dbuf.dptr);
5329 goto driver_deleted;
5332 dbuf = tdb_fetch_bystring(tdb_drivers, key);
5333 if (dbuf.dptr) {
5334 /* ok... the driver exists so the delete should return success */
5335 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5336 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5337 SAFE_FREE(key);
5338 SAFE_FREE(key8);
5339 return WERR_ACCESS_DENIED;
5341 SAFE_FREE(dbuf.dptr);
5342 goto driver_deleted;
5345 if (!dbuf.dptr) {
5346 DEBUG(8,("delete_printer_driver: Driver unknown\n"));
5347 return WERR_UNKNOWN_PRINTER_DRIVER;
5350 driver_deleted:
5352 * now delete any associated files if delete_files == True
5353 * even if this part failes, we return succes because the
5354 * driver doesn not exist any more
5357 if ( delete_files )
5358 delete_driver_files(rpc_pipe, r);
5360 DEBUG(5,("delete_printer_driver: driver delete successful\n"));
5362 return WERR_OK;
5365 /****************************************************************************
5366 Store a security desc for a printer.
5367 ****************************************************************************/
5369 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5371 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5372 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5373 TALLOC_CTX *mem_ctx = NULL;
5374 TDB_DATA kbuf;
5375 TDB_DATA dbuf;
5376 DATA_BLOB blob;
5377 WERROR status;
5378 NTSTATUS nt_status;
5380 mem_ctx = talloc_init("nt_printing_setsec");
5381 if (mem_ctx == NULL)
5382 return WERR_NOMEM;
5384 /* The old owner and group sids of the security descriptor are not
5385 present when new ACEs are added or removed by changing printer
5386 permissions through NT. If they are NULL in the new security
5387 descriptor then copy them over from the old one. */
5389 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5390 DOM_SID *owner_sid, *group_sid;
5391 SEC_ACL *dacl, *sacl;
5392 SEC_DESC *psd = NULL;
5393 size_t size;
5395 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5396 status = WERR_NOMEM;
5397 goto out;
5400 /* Pick out correct owner and group sids */
5402 owner_sid = secdesc_ctr->sd->owner_sid ?
5403 secdesc_ctr->sd->owner_sid :
5404 old_secdesc_ctr->sd->owner_sid;
5406 group_sid = secdesc_ctr->sd->group_sid ?
5407 secdesc_ctr->sd->group_sid :
5408 old_secdesc_ctr->sd->group_sid;
5410 dacl = secdesc_ctr->sd->dacl ?
5411 secdesc_ctr->sd->dacl :
5412 old_secdesc_ctr->sd->dacl;
5414 sacl = secdesc_ctr->sd->sacl ?
5415 secdesc_ctr->sd->sacl :
5416 old_secdesc_ctr->sd->sacl;
5418 /* Make a deep copy of the security descriptor */
5420 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5421 owner_sid, group_sid,
5422 sacl,
5423 dacl,
5424 &size);
5426 if (!psd) {
5427 status = WERR_NOMEM;
5428 goto out;
5431 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5434 if (!new_secdesc_ctr) {
5435 new_secdesc_ctr = secdesc_ctr;
5438 /* Store the security descriptor in a tdb */
5440 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5441 &blob.data, &blob.length);
5442 if (!NT_STATUS_IS_OK(nt_status)) {
5443 status = ntstatus_to_werror(nt_status);
5444 goto out;
5447 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5449 dbuf.dptr = (unsigned char *)blob.data;
5450 dbuf.dsize = blob.length;
5452 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5453 status = WERR_OK;
5454 } else {
5455 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5456 status = WERR_BADFUNC;
5459 /* Free malloc'ed memory */
5460 talloc_free(blob.data);
5462 out:
5464 if (mem_ctx)
5465 talloc_destroy(mem_ctx);
5466 return status;
5469 /****************************************************************************
5470 Construct a default security descriptor buffer for a printer.
5471 ****************************************************************************/
5473 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5475 SEC_ACE ace[5]; /* max number of ace entries */
5476 int i = 0;
5477 uint32_t sa;
5478 SEC_ACL *psa = NULL;
5479 SEC_DESC_BUF *sdb = NULL;
5480 SEC_DESC *psd = NULL;
5481 DOM_SID adm_sid;
5482 size_t sd_size;
5484 /* Create an ACE where Everyone is allowed to print */
5486 sa = PRINTER_ACE_PRINT;
5487 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5488 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5490 /* Add the domain admins group if we are a DC */
5492 if ( IS_DC ) {
5493 DOM_SID domadmins_sid;
5495 sid_compose(&domadmins_sid, get_global_sam_sid(),
5496 DOMAIN_GROUP_RID_ADMINS);
5498 sa = PRINTER_ACE_FULL_CONTROL;
5499 init_sec_ace(&ace[i++], &domadmins_sid,
5500 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5501 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5502 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5503 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5505 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5506 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5508 sa = PRINTER_ACE_FULL_CONTROL;
5509 init_sec_ace(&ace[i++], &adm_sid,
5510 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5511 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5512 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5513 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5516 /* add BUILTIN\Administrators as FULL CONTROL */
5518 sa = PRINTER_ACE_FULL_CONTROL;
5519 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5520 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5521 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5522 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5523 SEC_ACE_TYPE_ACCESS_ALLOWED,
5524 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5526 /* Make the security descriptor owned by the BUILTIN\Administrators */
5528 /* The ACL revision number in rpc_secdesc.h differs from the one
5529 created by NT when setting ACE entries in printer
5530 descriptors. NT4 complains about the property being edited by a
5531 NT5 machine. */
5533 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5534 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5535 &global_sid_Builtin_Administrators,
5536 &global_sid_Builtin_Administrators,
5537 NULL, psa, &sd_size);
5540 if (!psd) {
5541 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5542 return NULL;
5545 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5547 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5548 (unsigned int)sd_size));
5550 return sdb;
5553 /****************************************************************************
5554 Get a security desc for a printer.
5555 ****************************************************************************/
5557 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5559 TDB_DATA kbuf;
5560 TDB_DATA dbuf;
5561 DATA_BLOB blob;
5562 char *temp;
5563 NTSTATUS status;
5565 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5566 sharename = temp + 1;
5569 /* Fetch security descriptor from tdb */
5571 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5573 dbuf = tdb_fetch(tdb_printers, kbuf);
5574 if (dbuf.dptr) {
5576 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5577 secdesc_ctr);
5578 SAFE_FREE(dbuf.dptr);
5580 if (NT_STATUS_IS_OK(status)) {
5581 return true;
5585 *secdesc_ctr = construct_default_printer_sdb(ctx);
5586 if (!*secdesc_ctr) {
5587 return false;
5590 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5591 &blob.data, &blob.length);
5592 if (NT_STATUS_IS_OK(status)) {
5593 dbuf.dptr = (unsigned char *)blob.data;
5594 dbuf.dsize = blob.length;
5595 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5596 talloc_free(blob.data);
5599 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5600 this security descriptor has been created when winbindd was
5601 down. Take ownership of security descriptor. */
5603 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5604 DOM_SID owner_sid;
5606 /* Change sd owner to workgroup administrator */
5608 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5609 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5610 SEC_DESC *psd = NULL;
5611 size_t size;
5613 /* Create new sd */
5615 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5617 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5618 &owner_sid,
5619 (*secdesc_ctr)->sd->group_sid,
5620 (*secdesc_ctr)->sd->sacl,
5621 (*secdesc_ctr)->sd->dacl,
5622 &size);
5624 if (!psd) {
5625 return False;
5628 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5629 if (!new_secdesc_ctr) {
5630 return False;
5633 /* Swap with other one */
5635 *secdesc_ctr = new_secdesc_ctr;
5637 /* Set it */
5639 nt_printing_setsec(sharename, *secdesc_ctr);
5643 if (DEBUGLEVEL >= 10) {
5644 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5645 int i;
5647 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5648 sharename, the_acl->num_aces));
5650 for (i = 0; i < the_acl->num_aces; i++) {
5651 DEBUG(10, ("%s %d %d 0x%08x\n",
5652 sid_string_dbg(&the_acl->aces[i].trustee),
5653 the_acl->aces[i].type, the_acl->aces[i].flags,
5654 the_acl->aces[i].access_mask));
5658 return True;
5661 /* error code:
5662 0: everything OK
5663 1: level not implemented
5664 2: file doesn't exist
5665 3: can't allocate memory
5666 4: can't free memory
5667 5: non existant struct
5671 A printer and a printer driver are 2 different things.
5672 NT manages them separatelly, Samba does the same.
5673 Why ? Simply because it's easier and it makes sense !
5675 Now explanation: You have 3 printers behind your samba server,
5676 2 of them are the same make and model (laser A and B). But laser B
5677 has an 3000 sheet feeder and laser A doesn't such an option.
5678 Your third printer is an old dot-matrix model for the accounting :-).
5680 If the /usr/local/samba/lib directory (default dir), you will have
5681 5 files to describe all of this.
5683 3 files for the printers (1 by printer):
5684 NTprinter_laser A
5685 NTprinter_laser B
5686 NTprinter_accounting
5687 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5688 NTdriver_printer model X
5689 NTdriver_printer model Y
5691 jfm: I should use this comment for the text file to explain
5692 same thing for the forms BTW.
5693 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5697 /* Convert generic access rights to printer object specific access rights.
5698 It turns out that NT4 security descriptors use generic access rights and
5699 NT5 the object specific ones. */
5701 void map_printer_permissions(SEC_DESC *sd)
5703 int i;
5705 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5706 se_map_generic(&sd->dacl->aces[i].access_mask,
5707 &printer_generic_mapping);
5711 void map_job_permissions(SEC_DESC *sd)
5713 int i;
5715 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5716 se_map_generic(&sd->dacl->aces[i].access_mask,
5717 &job_generic_mapping);
5722 /****************************************************************************
5723 Check a user has permissions to perform the given operation. We use the
5724 permission constants defined in include/rpc_spoolss.h to check the various
5725 actions we perform when checking printer access.
5727 PRINTER_ACCESS_ADMINISTER:
5728 print_queue_pause, print_queue_resume, update_printer_sec,
5729 update_printer, spoolss_addprinterex_level_2,
5730 _spoolss_setprinterdata
5732 PRINTER_ACCESS_USE:
5733 print_job_start
5735 JOB_ACCESS_ADMINISTER:
5736 print_job_delete, print_job_pause, print_job_resume,
5737 print_queue_purge
5739 Try access control in the following order (for performance reasons):
5740 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5741 2) check security descriptor (bit comparisons in memory)
5742 3) "printer admins" (may result in numerous calls to winbind)
5744 ****************************************************************************/
5745 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5746 int access_type)
5748 SEC_DESC_BUF *secdesc = NULL;
5749 uint32 access_granted;
5750 NTSTATUS status;
5751 const char *pname;
5752 TALLOC_CTX *mem_ctx = NULL;
5753 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5755 /* If user is NULL then use the current_user structure */
5757 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5759 if (server_info->utok.uid == sec_initial_uid()
5760 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5761 return True;
5764 /* Get printer name */
5766 pname = PRINTERNAME(snum);
5768 if (!pname || !*pname) {
5769 errno = EACCES;
5770 return False;
5773 /* Get printer security descriptor */
5775 if(!(mem_ctx = talloc_init("print_access_check"))) {
5776 errno = ENOMEM;
5777 return False;
5780 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5781 talloc_destroy(mem_ctx);
5782 errno = ENOMEM;
5783 return False;
5786 if (access_type == JOB_ACCESS_ADMINISTER) {
5787 SEC_DESC_BUF *parent_secdesc = secdesc;
5789 /* Create a child security descriptor to check permissions
5790 against. This is because print jobs are child objects
5791 objects of a printer. */
5793 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5795 if (!NT_STATUS_IS_OK(status)) {
5796 talloc_destroy(mem_ctx);
5797 errno = map_errno_from_nt_status(status);
5798 return False;
5801 map_job_permissions(secdesc->sd);
5802 } else {
5803 map_printer_permissions(secdesc->sd);
5806 /* Check access */
5807 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5808 &access_granted);
5810 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5812 /* see if we need to try the printer admin list */
5814 if ((access_granted == 0) &&
5815 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5816 NULL, NULL, server_info->ptok,
5817 lp_printer_admin(snum)))) {
5818 talloc_destroy(mem_ctx);
5819 return True;
5822 talloc_destroy(mem_ctx);
5824 if (!NT_STATUS_IS_OK(status)) {
5825 errno = EACCES;
5828 return NT_STATUS_IS_OK(status);
5831 /****************************************************************************
5832 Check the time parameters allow a print operation.
5833 *****************************************************************************/
5835 bool print_time_access_check(const char *servicename)
5837 NT_PRINTER_INFO_LEVEL *printer = NULL;
5838 bool ok = False;
5839 time_t now = time(NULL);
5840 struct tm *t;
5841 uint32 mins;
5843 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5844 return False;
5846 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5847 ok = True;
5849 t = gmtime(&now);
5850 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5852 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5853 ok = True;
5855 free_a_printer(&printer, 2);
5857 if (!ok)
5858 errno = EACCES;
5860 return ok;
5863 /****************************************************************************
5864 Fill in the servername sent in the _spoolss_open_printer_ex() call
5865 ****************************************************************************/
5867 char* get_server_name( Printer_entry *printer )
5869 return printer->servername;