r25117: The mega-patch Jerry was waiting for. Remove all pstrings from
[Samba/nascimento.git] / source3 / printing / nt_printing.c
blob087af929559f711c72af2af677006c61604f21e8
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 extern struct current_user current_user;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43 /* Map generic permissions to printer object specific permissions */
45 GENERIC_MAPPING printer_generic_mapping = {
46 PRINTER_READ,
47 PRINTER_WRITE,
48 PRINTER_EXECUTE,
49 PRINTER_ALL_ACCESS
52 STANDARD_MAPPING printer_std_mapping = {
53 PRINTER_READ,
54 PRINTER_WRITE,
55 PRINTER_EXECUTE,
56 PRINTER_ALL_ACCESS
59 /* Map generic permissions to print server object specific permissions */
61 GENERIC_MAPPING printserver_generic_mapping = {
62 SERVER_READ,
63 SERVER_WRITE,
64 SERVER_EXECUTE,
65 SERVER_ALL_ACCESS
68 STANDARD_MAPPING printserver_std_mapping = {
69 SERVER_READ,
70 SERVER_WRITE,
71 SERVER_EXECUTE,
72 SERVER_ALL_ACCESS
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static const nt_forms_struct default_forms[] = {
80 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
200 struct table_node {
201 const char *long_archi;
202 const char *short_archi;
203 int version;
206 #define SPL_ARCH_WIN40 "WIN40"
207 #define SPL_ARCH_W32X86 "W32X86"
208 #define SPL_ARCH_W32MIPS "W32MIPS"
209 #define SPL_ARCH_W32ALPHA "W32ALPHA"
210 #define SPL_ARCH_W32PPC "W32PPC"
211 #define SPL_ARCH_IA64 "IA64"
212 #define SPL_ARCH_X64 "x64"
214 static const struct table_node archi_table[]= {
216 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
217 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
218 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
219 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
220 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
221 {"Windows IA64", SPL_ARCH_IA64, 3 },
222 {"Windows x64", SPL_ARCH_X64, 3 },
223 {NULL, "", -1 }
227 /****************************************************************************
228 generate a new TDB_DATA key for storing a printer
229 ****************************************************************************/
231 static TDB_DATA make_printer_tdbkey( const char *sharename )
233 fstring share;
234 static pstring keystr;
235 TDB_DATA key;
237 fstrcpy( share, sharename );
238 strlower_m( share );
240 pstr_sprintf( keystr, "%s%s", PRINTERS_PREFIX, share );
242 key = string_term_tdb_data(keystr);
244 return key;
247 /****************************************************************************
248 generate a new TDB_DATA key for storing a printer security descriptor
249 ****************************************************************************/
251 static TDB_DATA make_printers_secdesc_tdbkey( const char* sharename )
253 fstring share;
254 static pstring keystr;
255 TDB_DATA key;
257 fstrcpy( share, sharename );
258 strlower_m( share );
260 pstr_sprintf( keystr, "%s%s", SECDESC_PREFIX, share );
262 key = string_term_tdb_data(keystr);
264 return key;
267 /****************************************************************************
268 ****************************************************************************/
270 static BOOL upgrade_to_version_3(void)
272 TDB_DATA kbuf, newkey, dbuf;
274 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
276 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
277 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
279 dbuf = tdb_fetch(tdb_drivers, kbuf);
281 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
282 DEBUG(0,("upgrade_to_version_3:moving form\n"));
283 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
284 SAFE_FREE(dbuf.dptr);
285 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
286 return False;
288 if (tdb_delete(tdb_drivers, kbuf) != 0) {
289 SAFE_FREE(dbuf.dptr);
290 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
291 return False;
295 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
296 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
297 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
298 SAFE_FREE(dbuf.dptr);
299 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
300 return False;
302 if (tdb_delete(tdb_drivers, kbuf) != 0) {
303 SAFE_FREE(dbuf.dptr);
304 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
305 return False;
309 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
310 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
311 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
312 SAFE_FREE(dbuf.dptr);
313 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
314 return False;
316 if (tdb_delete(tdb_drivers, kbuf) != 0) {
317 SAFE_FREE(dbuf.dptr);
318 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
319 return False;
323 SAFE_FREE(dbuf.dptr);
326 return True;
329 /*******************************************************************
330 Fix an issue with security descriptors. Printer sec_desc must
331 use more than the generic bits that were previously used
332 in <= 3.0.14a. They must also have a owner and group SID assigned.
333 Otherwise, any printers than have been migrated to a Windows
334 host using printmig.exe will not be accessible.
335 *******************************************************************/
337 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
338 TDB_DATA data, void *state )
340 prs_struct ps;
341 SEC_DESC_BUF *sd_orig = NULL;
342 SEC_DESC_BUF *sd_new, *sd_store;
343 SEC_DESC *sec, *new_sec;
344 TALLOC_CTX *ctx = state;
345 int result, i;
346 uint32 sd_size;
347 size_t size_new_sec;
348 DOM_SID sid;
350 if (!data.dptr || data.dsize == 0) {
351 return 0;
354 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
355 return 0;
358 /* upgrade the security descriptor */
360 ZERO_STRUCT( ps );
362 prs_init( &ps, 0, ctx, UNMARSHALL );
363 prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
365 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
366 /* delete bad entries */
367 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
368 (const char *)key.dptr ));
369 tdb_delete( tdb_printers, key );
370 prs_mem_free( &ps );
371 return 0;
374 if (!sd_orig) {
375 prs_mem_free( &ps );
376 return 0;
378 sec = sd_orig->sd;
380 /* is this even valid? */
382 if ( !sec->dacl ) {
383 prs_mem_free( &ps );
384 return 0;
387 /* update access masks */
389 for ( i=0; i<sec->dacl->num_aces; i++ ) {
390 switch ( sec->dacl->aces[i].access_mask ) {
391 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
392 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
393 break;
395 case GENERIC_ALL_ACCESS:
396 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
397 break;
399 case READ_CONTROL_ACCESS:
400 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
402 default: /* no change */
403 break;
407 /* create a new SEC_DESC with the appropriate owner and group SIDs */
409 string_to_sid(&sid, "S-1-5-32-544" );
410 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
411 &sid, &sid,
412 NULL, NULL, &size_new_sec );
413 if (!new_sec) {
414 prs_mem_free( &ps );
415 return 0;
417 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
418 if (!sd_new) {
419 prs_mem_free( &ps );
420 return 0;
423 if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
424 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
425 prs_mem_free( &ps );
426 return 0;
429 prs_mem_free( &ps );
431 /* store it back */
433 sd_size = sec_desc_size(sd_store->sd) + sizeof(SEC_DESC_BUF);
434 prs_init(&ps, sd_size, ctx, MARSHALL);
436 if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
437 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
438 prs_mem_free( &ps );
439 return 0;
442 data.dptr = (uint8 *)prs_data_p( &ps );
443 data.dsize = sd_size;
445 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
447 prs_mem_free( &ps );
449 /* 0 to continue and non-zero to stop traversal */
451 return (result == -1);
454 /*******************************************************************
455 *******************************************************************/
457 static BOOL upgrade_to_version_4(void)
459 TALLOC_CTX *ctx;
460 int result;
462 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
464 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
465 return False;
467 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
469 talloc_destroy( ctx );
471 return ( result != -1 );
474 /*******************************************************************
475 Fix an issue with security descriptors. Printer sec_desc must
476 use more than the generic bits that were previously used
477 in <= 3.0.14a. They must also have a owner and group SID assigned.
478 Otherwise, any printers than have been migrated to a Windows
479 host using printmig.exe will not be accessible.
480 *******************************************************************/
482 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
483 TDB_DATA data, void *state )
485 TDB_DATA new_key;
487 if (!data.dptr || data.dsize == 0)
488 return 0;
490 /* upgrade printer records and security descriptors */
492 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
493 new_key = make_printer_tdbkey( (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
495 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
496 new_key = make_printers_secdesc_tdbkey( (const char *)key.dptr+strlen(SECDESC_PREFIX) );
498 else {
499 /* ignore this record */
500 return 0;
503 /* delete the original record and store under the normalized key */
505 if ( tdb_delete( the_tdb, key ) != 0 ) {
506 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
507 key.dptr));
508 return 1;
511 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
512 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
513 key.dptr));
514 return 1;
517 return 0;
520 /*******************************************************************
521 *******************************************************************/
523 static BOOL upgrade_to_version_5(void)
525 TALLOC_CTX *ctx;
526 int result;
528 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
530 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
531 return False;
533 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
535 talloc_destroy( ctx );
537 return ( result != -1 );
540 /****************************************************************************
541 Open the NT printing tdbs. Done once before fork().
542 ****************************************************************************/
544 BOOL nt_printing_init(struct messaging_context *msg_ctx)
546 const char *vstring = "INFO/version";
547 WERROR win_rc;
548 int32 vers_id;
550 if ( tdb_drivers && tdb_printers && tdb_forms )
551 return True;
553 if (tdb_drivers)
554 tdb_close(tdb_drivers);
555 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
556 if (!tdb_drivers) {
557 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
558 lock_path("ntdrivers.tdb"), strerror(errno) ));
559 return False;
562 if (tdb_printers)
563 tdb_close(tdb_printers);
564 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
565 if (!tdb_printers) {
566 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
567 lock_path("ntprinters.tdb"), strerror(errno) ));
568 return False;
571 if (tdb_forms)
572 tdb_close(tdb_forms);
573 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
574 if (!tdb_forms) {
575 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
576 lock_path("ntforms.tdb"), strerror(errno) ));
577 return False;
580 /* handle a Samba upgrade */
582 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
583 if (vers_id == -1) {
584 DEBUG(10, ("Fresh database\n"));
585 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
586 vers_id = NTDRIVERS_DATABASE_VERSION_5;
589 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
591 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
592 if (!upgrade_to_version_3())
593 return False;
594 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
595 vers_id = NTDRIVERS_DATABASE_VERSION_3;
598 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
599 /* Written on a bigendian machine with old fetch_int code. Save as le. */
600 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
601 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
602 vers_id = NTDRIVERS_DATABASE_VERSION_3;
605 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
606 if ( !upgrade_to_version_4() )
607 return False;
608 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
609 vers_id = NTDRIVERS_DATABASE_VERSION_4;
612 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
613 if ( !upgrade_to_version_5() )
614 return False;
615 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
616 vers_id = NTDRIVERS_DATABASE_VERSION_5;
620 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
621 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
622 return False;
626 update_c_setprinter(True);
629 * register callback to handle updating printers as new
630 * drivers are installed
633 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
634 do_drv_upgrade_printer);
637 * register callback to handle updating printer data
638 * when a driver is initialized
641 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
642 reset_all_printerdata);
644 /* of course, none of the message callbacks matter if you don't
645 tell messages.c that you interested in receiving PRINT_GENERAL
646 msgs. This is done in claim_connection() */
649 if ( lp_security() == SEC_ADS ) {
650 win_rc = check_published_printers();
651 if (!W_ERROR_IS_OK(win_rc))
652 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
655 return True;
658 /*******************************************************************
659 Function to allow filename parsing "the old way".
660 ********************************************************************/
662 static void driver_unix_convert(connection_struct *conn,
663 pstring name,
664 SMB_STRUCT_STAT *pst)
666 char *new_name = NULL;
667 unix_format(name);
668 unix_clean_name(name);
669 trim_string(name,"/","/");
670 unix_convert(conn, name, False, &new_name, NULL, pst);
671 if (new_name) {
672 pstrcpy(name, new_name);
676 /*******************************************************************
677 tdb traversal function for counting printers.
678 ********************************************************************/
680 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
681 TDB_DATA data, void *context)
683 int *printer_count = (int*)context;
685 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
686 (*printer_count)++;
687 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
690 return 0;
693 /*******************************************************************
694 Update the spooler global c_setprinter. This variable is initialized
695 when the parent smbd starts with the number of existing printers. It
696 is monotonically increased by the current number of printers *after*
697 each add or delete printer RPC. Only Microsoft knows why... JRR020119
698 ********************************************************************/
700 uint32 update_c_setprinter(BOOL initialize)
702 int32 c_setprinter;
703 int32 printer_count = 0;
705 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
707 /* Traverse the tdb, counting the printers */
708 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
710 /* If initializing, set c_setprinter to current printers count
711 * otherwise, bump it by the current printer count
713 if (!initialize)
714 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
715 else
716 c_setprinter = printer_count;
718 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
719 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
721 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
723 return (uint32)c_setprinter;
726 /*******************************************************************
727 Get the spooler global c_setprinter, accounting for initialization.
728 ********************************************************************/
730 uint32 get_c_setprinter(void)
732 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
734 if (c_setprinter == (int32)-1)
735 c_setprinter = update_c_setprinter(True);
737 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
739 return (uint32)c_setprinter;
742 /****************************************************************************
743 Get builtin form struct list.
744 ****************************************************************************/
746 int get_builtin_ntforms(nt_forms_struct **list)
748 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
749 if (!*list) {
750 return 0;
752 return sizeof(default_forms) / sizeof(default_forms[0]);
755 /****************************************************************************
756 get a builtin form struct
757 ****************************************************************************/
759 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
761 int i,count;
762 fstring form_name;
763 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
764 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
765 count = sizeof(default_forms) / sizeof(default_forms[0]);
766 for (i=0;i<count;i++) {
767 if (strequal(form_name,default_forms[i].name)) {
768 DEBUGADD(6,("Found builtin form %s \n", form_name));
769 memcpy(form,&default_forms[i],sizeof(*form));
770 break;
774 return (i !=count);
777 /****************************************************************************
778 get a form struct list.
779 ****************************************************************************/
781 int get_ntforms(nt_forms_struct **list)
783 TDB_DATA kbuf, newkey, dbuf;
784 nt_forms_struct form;
785 int ret;
786 int i;
787 int n = 0;
789 *list = NULL;
791 for (kbuf = tdb_firstkey(tdb_forms);
792 kbuf.dptr;
793 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
795 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
796 continue;
798 dbuf = tdb_fetch(tdb_forms, kbuf);
799 if (!dbuf.dptr)
800 continue;
802 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
803 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
804 &i, &form.flag, &form.width, &form.length, &form.left,
805 &form.top, &form.right, &form.bottom);
806 SAFE_FREE(dbuf.dptr);
807 if (ret != dbuf.dsize)
808 continue;
810 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
811 if (!*list) {
812 DEBUG(0,("get_ntforms: Realloc fail.\n"));
813 return 0;
815 (*list)[n] = form;
816 n++;
820 return n;
823 /****************************************************************************
824 write a form struct list
825 ****************************************************************************/
826 int write_ntforms(nt_forms_struct **list, int number)
828 pstring buf, key;
829 int len;
830 TDB_DATA dbuf;
831 int i;
833 for (i=0;i<number;i++) {
834 /* save index, so list is rebuilt in correct order */
835 len = tdb_pack((uint8 *)buf, sizeof(buf), "dddddddd",
836 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
837 (*list)[i].left, (*list)[i].top, (*list)[i].right,
838 (*list)[i].bottom);
839 if (len > sizeof(buf)) break;
840 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
841 dbuf.dsize = len;
842 dbuf.dptr = (uint8 *)buf;
843 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) break;
846 return i;
849 /****************************************************************************
850 add a form struct at the end of the list
851 ****************************************************************************/
852 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
854 int n=0;
855 BOOL update;
856 fstring form_name;
859 * NT tries to add forms even when
860 * they are already in the base
861 * only update the values if already present
864 update=False;
866 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
867 for (n=0; n<*count; n++) {
868 if ( strequal((*list)[n].name, form_name) ) {
869 update=True;
870 break;
874 if (update==False) {
875 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
876 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
877 return False;
879 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
880 (*count)++;
883 (*list)[n].flag=form->flags;
884 (*list)[n].width=form->size_x;
885 (*list)[n].length=form->size_y;
886 (*list)[n].left=form->left;
887 (*list)[n].top=form->top;
888 (*list)[n].right=form->right;
889 (*list)[n].bottom=form->bottom;
891 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
892 update ? "updated" : "added", form_name));
894 return True;
897 /****************************************************************************
898 Delete a named form struct.
899 ****************************************************************************/
901 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
903 pstring key;
904 int n=0;
905 fstring form_name;
907 *ret = WERR_OK;
909 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
911 for (n=0; n<*count; n++) {
912 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
913 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
914 break;
918 if (n == *count) {
919 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
920 *ret = WERR_INVALID_PARAM;
921 return False;
924 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
925 if (tdb_delete_bystring(tdb_forms, key) != 0) {
926 *ret = WERR_NOMEM;
927 return False;
930 return True;
933 /****************************************************************************
934 Update a form struct.
935 ****************************************************************************/
937 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
939 int n=0;
940 fstring form_name;
941 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
943 DEBUG(106, ("[%s]\n", form_name));
944 for (n=0; n<count; n++) {
945 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
946 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
947 break;
950 if (n==count) return;
952 (*list)[n].flag=form->flags;
953 (*list)[n].width=form->size_x;
954 (*list)[n].length=form->size_y;
955 (*list)[n].left=form->left;
956 (*list)[n].top=form->top;
957 (*list)[n].right=form->right;
958 (*list)[n].bottom=form->bottom;
961 /****************************************************************************
962 Get the nt drivers list.
963 Traverse the database and look-up the matching names.
964 ****************************************************************************/
965 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
967 int total=0;
968 const char *short_archi;
969 pstring key;
970 TDB_DATA kbuf, newkey;
972 short_archi = get_short_archi(architecture);
973 if (!short_archi) {
974 return 0;
977 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
979 for (kbuf = tdb_firstkey(tdb_drivers);
980 kbuf.dptr;
981 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
983 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
984 continue;
986 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
987 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
988 return -1;
991 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
992 total++;
995 return(total);
998 /****************************************************************************
999 Function to do the mapping between the long architecture name and
1000 the short one.
1001 ****************************************************************************/
1003 const char *get_short_archi(const char *long_archi)
1005 int i=-1;
1007 DEBUG(107,("Getting architecture dependant directory\n"));
1008 do {
1009 i++;
1010 } while ( (archi_table[i].long_archi!=NULL ) &&
1011 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1013 if (archi_table[i].long_archi==NULL) {
1014 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1015 return NULL;
1018 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1020 DEBUGADD(108,("index: [%d]\n", i));
1021 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1022 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1024 return archi_table[i].short_archi;
1027 /****************************************************************************
1028 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1029 There are two case to be covered here: PE (Portable Executable) and NE (New
1030 Executable) files. Both files support the same INFO structure, but PE files
1031 store the signature in unicode, and NE files store it as !unicode.
1032 returns -1 on error, 1 on version info found, and 0 on no version info found.
1033 ****************************************************************************/
1035 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1037 int i;
1038 char *buf = NULL;
1039 ssize_t byte_count;
1041 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1042 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1043 fname, DOS_HEADER_SIZE));
1044 goto error_exit;
1047 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1048 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1049 fname, (unsigned long)byte_count));
1050 goto no_version_info;
1053 /* Is this really a DOS header? */
1054 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1055 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1056 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1057 goto no_version_info;
1060 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1061 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1062 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1063 fname, errno));
1064 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1065 goto no_version_info;
1068 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1069 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1070 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1071 fname, (unsigned long)byte_count));
1072 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1073 goto no_version_info;
1076 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1077 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1078 unsigned int num_sections;
1079 unsigned int section_table_bytes;
1081 /* Just skip over optional header to get to section table */
1082 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
1083 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1084 SEEK_CUR) == (SMB_OFF_T)-1) {
1085 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1086 fname, errno));
1087 goto error_exit;
1090 /* get the section table */
1091 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1092 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1093 if (section_table_bytes == 0)
1094 goto error_exit;
1096 SAFE_FREE(buf);
1097 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1098 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1099 fname, section_table_bytes));
1100 goto error_exit;
1103 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1104 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1105 fname, (unsigned long)byte_count));
1106 goto error_exit;
1109 /* Iterate the section table looking for the resource section ".rsrc" */
1110 for (i = 0; i < num_sections; i++) {
1111 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1113 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1114 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1115 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1117 if (section_bytes == 0)
1118 goto error_exit;
1120 SAFE_FREE(buf);
1121 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1122 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1123 fname, section_bytes));
1124 goto error_exit;
1127 /* Seek to the start of the .rsrc section info */
1128 if (SMB_VFS_LSEEK(fsp, fsp->fh->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1129 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1130 fname, errno));
1131 goto error_exit;
1134 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1135 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1136 fname, (unsigned long)byte_count));
1137 goto error_exit;
1140 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1141 goto error_exit;
1143 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1144 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1145 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1146 /* Align to next long address */
1147 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1149 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1150 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1151 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1153 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1154 fname, *major, *minor,
1155 (*major>>16)&0xffff, *major&0xffff,
1156 (*minor>>16)&0xffff, *minor&0xffff));
1157 SAFE_FREE(buf);
1158 return 1;
1165 /* Version info not found, fall back to origin date/time */
1166 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1167 SAFE_FREE(buf);
1168 return 0;
1170 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1171 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1172 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1173 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1174 /* At this point, we assume the file is in error. It still could be somthing
1175 * else besides a NE file, but it unlikely at this point. */
1176 goto error_exit;
1179 /* Allocate a bit more space to speed up things */
1180 SAFE_FREE(buf);
1181 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1182 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1183 fname, PE_HEADER_SIZE));
1184 goto error_exit;
1187 /* This is a HACK! I got tired of trying to sort through the messy
1188 * 'NE' file format. If anyone wants to clean this up please have at
1189 * it, but this works. 'NE' files will eventually fade away. JRR */
1190 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1191 /* Cover case that should not occur in a well formed 'NE' .dll file */
1192 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1194 for(i=0; i<byte_count; i++) {
1195 /* Fast skip past data that can't possibly match */
1196 if (buf[i] != 'V') continue;
1198 /* Potential match data crosses buf boundry, move it to beginning
1199 * of buf, and fill the buf with as much as it will hold. */
1200 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1201 int bc;
1203 memcpy(buf, &buf[i], byte_count-i);
1204 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1205 (byte_count-i))) < 0) {
1207 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1208 fname, errno));
1209 goto error_exit;
1212 byte_count = bc + (byte_count - i);
1213 if (byte_count<VS_VERSION_INFO_SIZE) break;
1215 i = 0;
1218 /* Check that the full signature string and the magic number that
1219 * follows exist (not a perfect solution, but the chances that this
1220 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1221 * twice, as it is simpler to read the code. */
1222 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1223 /* Compute skip alignment to next long address */
1224 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fh->fd, 0, SEEK_CUR) - (byte_count - i) +
1225 sizeof(VS_SIGNATURE)) & 3;
1226 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1228 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1229 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1230 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1231 fname, *major, *minor,
1232 (*major>>16)&0xffff, *major&0xffff,
1233 (*minor>>16)&0xffff, *minor&0xffff));
1234 SAFE_FREE(buf);
1235 return 1;
1240 /* Version info not found, fall back to origin date/time */
1241 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1242 SAFE_FREE(buf);
1243 return 0;
1245 } else
1246 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1247 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1248 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1250 no_version_info:
1251 SAFE_FREE(buf);
1252 return 0;
1254 error_exit:
1255 SAFE_FREE(buf);
1256 return -1;
1259 /****************************************************************************
1260 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1261 share one or more files. During the MS installation process files are checked
1262 to insure that only a newer version of a shared file is installed over an
1263 older version. There are several possibilities for this comparison. If there
1264 is no previous version, the new one is newer (obviously). If either file is
1265 missing the version info structure, compare the creation date (on Unix use
1266 the modification date). Otherwise chose the numerically larger version number.
1267 ****************************************************************************/
1269 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1271 BOOL use_version = True;
1272 pstring filepath;
1274 uint32 new_major;
1275 uint32 new_minor;
1276 time_t new_create_time;
1278 uint32 old_major;
1279 uint32 old_minor;
1280 time_t old_create_time;
1282 files_struct *fsp = NULL;
1283 SMB_STRUCT_STAT st;
1284 SMB_STRUCT_STAT stat_buf;
1286 NTSTATUS status;
1288 SET_STAT_INVALID(st);
1289 SET_STAT_INVALID(stat_buf);
1290 new_create_time = (time_t)0;
1291 old_create_time = (time_t)0;
1293 /* Get file version info (if available) for previous file (if it exists) */
1294 pstrcpy(filepath, old_file);
1296 driver_unix_convert(conn,filepath,&stat_buf);
1298 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1299 FILE_GENERIC_READ,
1300 FILE_SHARE_READ|FILE_SHARE_WRITE,
1301 FILE_OPEN,
1303 FILE_ATTRIBUTE_NORMAL,
1304 INTERNAL_OPEN_ONLY,
1305 NULL, &fsp);
1307 if (!NT_STATUS_IS_OK(status)) {
1308 /* Old file not found, so by definition new file is in fact newer */
1309 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1310 filepath, errno));
1311 return True;
1313 } else {
1314 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1315 if (ret == -1) {
1316 goto error_exit;
1319 if (!ret) {
1320 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1321 old_file));
1322 use_version = False;
1323 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1324 old_create_time = st.st_mtime;
1325 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1328 close_file(fsp, NORMAL_CLOSE);
1330 /* Get file version info (if available) for new file */
1331 pstrcpy(filepath, new_file);
1332 driver_unix_convert(conn,filepath,&stat_buf);
1334 status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
1335 FILE_GENERIC_READ,
1336 FILE_SHARE_READ|FILE_SHARE_WRITE,
1337 FILE_OPEN,
1339 FILE_ATTRIBUTE_NORMAL,
1340 INTERNAL_OPEN_ONLY,
1341 NULL, &fsp);
1343 if (!NT_STATUS_IS_OK(status)) {
1344 /* New file not found, this shouldn't occur if the caller did its job */
1345 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1346 filepath, errno));
1347 goto error_exit;
1349 } else {
1350 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1351 if (ret == -1) {
1352 goto error_exit;
1355 if (!ret) {
1356 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1357 new_file));
1358 use_version = False;
1359 if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &st) == -1) goto error_exit;
1360 new_create_time = st.st_mtime;
1361 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1364 close_file(fsp, NORMAL_CLOSE);
1366 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1367 /* Compare versions and choose the larger version number */
1368 if (new_major > old_major ||
1369 (new_major == old_major && new_minor > old_minor)) {
1371 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1372 return True;
1374 else {
1375 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1376 return False;
1379 } else {
1380 /* Compare modification time/dates and choose the newest time/date */
1381 if (new_create_time > old_create_time) {
1382 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1383 return True;
1385 else {
1386 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1387 return False;
1391 error_exit:
1392 if(fsp)
1393 close_file(fsp, NORMAL_CLOSE);
1394 return -1;
1397 /****************************************************************************
1398 Determine the correct cVersion associated with an architecture and driver
1399 ****************************************************************************/
1400 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1401 struct current_user *user, WERROR *perr)
1403 int cversion;
1404 NTSTATUS nt_status;
1405 pstring driverpath;
1406 DATA_BLOB null_pw;
1407 fstring res_type;
1408 files_struct *fsp = NULL;
1409 SMB_STRUCT_STAT st;
1410 connection_struct *conn;
1411 NTSTATUS status;
1413 SET_STAT_INVALID(st);
1415 *perr = WERR_INVALID_PARAM;
1417 /* If architecture is Windows 95/98/ME, the version is always 0. */
1418 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1419 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1420 *perr = WERR_OK;
1421 return 0;
1424 /* If architecture is Windows x64, the version is always 3. */
1425 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1426 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1427 *perr = WERR_OK;
1428 return 3;
1432 * Connect to the print$ share under the same account as the user connected
1433 * to the rpc pipe. Note we must still be root to do this.
1436 /* Null password is ok - we are already an authenticated user... */
1437 null_pw = data_blob_null;
1438 fstrcpy(res_type, "A:");
1439 become_root();
1440 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1441 unbecome_root();
1443 if (conn == NULL) {
1444 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1445 *perr = ntstatus_to_werror(nt_status);
1446 return -1;
1449 /* We are temporarily becoming the connection user. */
1450 if (!become_user(conn, user->vuid)) {
1451 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1452 *perr = WERR_ACCESS_DENIED;
1453 return -1;
1456 /* Open the driver file (Portable Executable format) and determine the
1457 * deriver the cversion. */
1458 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1460 driver_unix_convert(conn,driverpath,&st);
1462 if ( !vfs_file_exist( conn, driverpath, &st ) ) {
1463 *perr = WERR_BADFILE;
1464 goto error_exit;
1467 status = open_file_ntcreate(conn, NULL, driverpath, &st,
1468 FILE_GENERIC_READ,
1469 FILE_SHARE_READ|FILE_SHARE_WRITE,
1470 FILE_OPEN,
1472 FILE_ATTRIBUTE_NORMAL,
1473 INTERNAL_OPEN_ONLY,
1474 NULL, &fsp);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1478 driverpath, errno));
1479 *perr = WERR_ACCESS_DENIED;
1480 goto error_exit;
1481 } else {
1482 uint32 major;
1483 uint32 minor;
1484 int ret = get_file_version(fsp, driverpath, &major, &minor);
1485 if (ret == -1) goto error_exit;
1487 if (!ret) {
1488 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1489 goto error_exit;
1493 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1494 * for more details. Version in this case is not just the version of the
1495 * file, but the version in the sense of kernal mode (2) vs. user mode
1496 * (3) drivers. Other bits of the version fields are the version info.
1497 * JRR 010716
1499 cversion = major & 0x0000ffff;
1500 switch (cversion) {
1501 case 2: /* WinNT drivers */
1502 case 3: /* Win2K drivers */
1503 break;
1505 default:
1506 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1507 driverpath, cversion));
1508 goto error_exit;
1511 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1512 driverpath, major, minor));
1515 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1516 driverpath, cversion));
1518 close_file(fsp, NORMAL_CLOSE);
1519 close_cnum(conn, user->vuid);
1520 unbecome_user();
1521 *perr = WERR_OK;
1522 return cversion;
1525 error_exit:
1527 if(fsp)
1528 close_file(fsp, NORMAL_CLOSE);
1530 close_cnum(conn, user->vuid);
1531 unbecome_user();
1532 return -1;
1535 /****************************************************************************
1536 ****************************************************************************/
1537 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1538 struct current_user *user)
1540 const char *architecture;
1541 fstring new_name;
1542 char *p;
1543 int i;
1544 WERROR err;
1546 /* clean up the driver name.
1547 * we can get .\driver.dll
1548 * or worse c:\windows\system\driver.dll !
1550 /* using an intermediate string to not have overlaping memcpy()'s */
1551 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1552 fstrcpy(new_name, p+1);
1553 fstrcpy(driver->driverpath, new_name);
1556 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1557 fstrcpy(new_name, p+1);
1558 fstrcpy(driver->datafile, new_name);
1561 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1562 fstrcpy(new_name, p+1);
1563 fstrcpy(driver->configfile, new_name);
1566 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1567 fstrcpy(new_name, p+1);
1568 fstrcpy(driver->helpfile, new_name);
1571 if (driver->dependentfiles) {
1572 for (i=0; *driver->dependentfiles[i]; i++) {
1573 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1574 fstrcpy(new_name, p+1);
1575 fstrcpy(driver->dependentfiles[i], new_name);
1580 architecture = get_short_archi(driver->environment);
1581 if (!architecture) {
1582 return WERR_UNKNOWN_PRINTER_DRIVER;
1585 /* jfm:7/16/2000 the client always sends the cversion=0.
1586 * The server should check which version the driver is by reading
1587 * the PE header of driver->driverpath.
1589 * For Windows 95/98 the version is 0 (so the value sent is correct)
1590 * For Windows NT (the architecture doesn't matter)
1591 * NT 3.1: cversion=0
1592 * NT 3.5/3.51: cversion=1
1593 * NT 4: cversion=2
1594 * NT2K: cversion=3
1596 if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
1597 return err;
1599 return WERR_OK;
1602 /****************************************************************************
1603 ****************************************************************************/
1604 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1606 const char *architecture;
1607 fstring new_name;
1608 char *p;
1609 int i;
1610 WERROR err;
1612 /* clean up the driver name.
1613 * we can get .\driver.dll
1614 * or worse c:\windows\system\driver.dll !
1616 /* using an intermediate string to not have overlaping memcpy()'s */
1617 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1618 fstrcpy(new_name, p+1);
1619 fstrcpy(driver->driverpath, new_name);
1622 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1623 fstrcpy(new_name, p+1);
1624 fstrcpy(driver->datafile, new_name);
1627 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1628 fstrcpy(new_name, p+1);
1629 fstrcpy(driver->configfile, new_name);
1632 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1633 fstrcpy(new_name, p+1);
1634 fstrcpy(driver->helpfile, new_name);
1637 if (driver->dependentfiles) {
1638 for (i=0; *driver->dependentfiles[i]; i++) {
1639 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1640 fstrcpy(new_name, p+1);
1641 fstrcpy(driver->dependentfiles[i], new_name);
1646 architecture = get_short_archi(driver->environment);
1647 if (!architecture) {
1648 return WERR_UNKNOWN_PRINTER_DRIVER;
1651 /* jfm:7/16/2000 the client always sends the cversion=0.
1652 * The server should check which version the driver is by reading
1653 * the PE header of driver->driverpath.
1655 * For Windows 95/98 the version is 0 (so the value sent is correct)
1656 * For Windows NT (the architecture doesn't matter)
1657 * NT 3.1: cversion=0
1658 * NT 3.5/3.51: cversion=1
1659 * NT 4: cversion=2
1660 * NT2K: cversion=3
1663 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1664 return err;
1666 return WERR_OK;
1669 /****************************************************************************
1670 ****************************************************************************/
1671 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1672 uint32 level, struct current_user *user)
1674 switch (level) {
1675 case 3:
1677 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1678 driver=driver_abstract.info_3;
1679 return clean_up_driver_struct_level_3(driver, user);
1681 case 6:
1683 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1684 driver=driver_abstract.info_6;
1685 return clean_up_driver_struct_level_6(driver, user);
1687 default:
1688 return WERR_INVALID_PARAM;
1692 /****************************************************************************
1693 This function sucks and should be replaced. JRA.
1694 ****************************************************************************/
1696 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1698 dst->cversion = src->version;
1700 fstrcpy( dst->name, src->name);
1701 fstrcpy( dst->environment, src->environment);
1702 fstrcpy( dst->driverpath, src->driverpath);
1703 fstrcpy( dst->datafile, src->datafile);
1704 fstrcpy( dst->configfile, src->configfile);
1705 fstrcpy( dst->helpfile, src->helpfile);
1706 fstrcpy( dst->monitorname, src->monitorname);
1707 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1708 dst->dependentfiles = src->dependentfiles;
1711 #if 0 /* Debugging function */
1713 static char* ffmt(unsigned char *c){
1714 int i;
1715 static char ffmt_str[17];
1717 for (i=0; i<16; i++) {
1718 if ((c[i] < ' ') || (c[i] > '~'))
1719 ffmt_str[i]='.';
1720 else
1721 ffmt_str[i]=c[i];
1723 ffmt_str[16]='\0';
1724 return ffmt_str;
1727 #endif
1729 /****************************************************************************
1730 ****************************************************************************/
1731 WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1732 struct current_user *user, WERROR *perr)
1734 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1735 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1736 const char *architecture;
1737 pstring new_dir;
1738 pstring old_name;
1739 pstring new_name;
1740 DATA_BLOB null_pw;
1741 connection_struct *conn;
1742 NTSTATUS nt_status;
1743 pstring inbuf;
1744 pstring outbuf;
1745 fstring res_type;
1746 SMB_STRUCT_STAT st;
1747 int ver = 0;
1748 int i;
1749 TALLOC_CTX *ctx = talloc_tos();
1751 memset(inbuf, '\0', sizeof(inbuf));
1752 memset(outbuf, '\0', sizeof(outbuf));
1753 *perr = WERR_OK;
1755 if (level==3)
1756 driver=driver_abstract.info_3;
1757 else if (level==6) {
1758 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1759 driver = &converted_driver;
1760 } else {
1761 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1762 return WERR_UNKNOWN_LEVEL;
1765 architecture = get_short_archi(driver->environment);
1766 if (!architecture) {
1767 return WERR_UNKNOWN_PRINTER_DRIVER;
1771 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1772 * Note we must be root to do this.
1775 null_pw = data_blob_null;
1776 fstrcpy(res_type, "A:");
1777 become_root();
1778 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1779 unbecome_root();
1781 if (conn == NULL) {
1782 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1783 *perr = ntstatus_to_werror(nt_status);
1784 return WERR_NO_SUCH_SHARE;
1788 * Save who we are - we are temporarily becoming the connection user.
1791 if (!become_user(conn, conn->vuid)) {
1792 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1793 return WERR_ACCESS_DENIED;
1797 * make the directories version and version\driver_name
1798 * under the architecture directory.
1800 DEBUG(5,("Creating first directory\n"));
1801 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1802 driver_unix_convert(conn,new_dir,&st);
1803 create_directory(conn, new_dir);
1805 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1806 * listed for this driver which has already been moved, skip it (note:
1807 * drivers may list the same file name several times. Then check if the
1808 * file already exists in archi\cversion\, if so, check that the version
1809 * info (or time stamps if version info is unavailable) is newer (or the
1810 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1811 * Otherwise, delete the file.
1813 * If a file is not moved to archi\cversion\ because of an error, all the
1814 * rest of the 'unmoved' driver files are removed from archi\. If one or
1815 * more of the driver's files was already moved to archi\cversion\, it
1816 * potentially leaves the driver in a partially updated state. Version
1817 * trauma will most likely occur if an client attempts to use any printer
1818 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1819 * done is appropriate... later JRR
1822 DEBUG(5,("Moving files now !\n"));
1824 if (driver->driverpath && strlen(driver->driverpath)) {
1825 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1826 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1827 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1828 driver_unix_convert(conn,new_name,&st);
1829 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1830 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1831 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1832 new_name, old_name));
1833 *perr = WERR_ACCESS_DENIED;
1834 ver = -1;
1839 if (driver->datafile && strlen(driver->datafile)) {
1840 if (!strequal(driver->datafile, driver->driverpath)) {
1841 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1842 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1843 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1844 driver_unix_convert(conn,new_name,&st);
1845 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1846 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1847 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1848 new_name, old_name));
1849 *perr = WERR_ACCESS_DENIED;
1850 ver = -1;
1856 if (driver->configfile && strlen(driver->configfile)) {
1857 if (!strequal(driver->configfile, driver->driverpath) &&
1858 !strequal(driver->configfile, driver->datafile)) {
1859 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1860 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1861 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1862 driver_unix_convert(conn,new_name,&st);
1863 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1864 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1865 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1866 new_name, old_name));
1867 *perr = WERR_ACCESS_DENIED;
1868 ver = -1;
1874 if (driver->helpfile && strlen(driver->helpfile)) {
1875 if (!strequal(driver->helpfile, driver->driverpath) &&
1876 !strequal(driver->helpfile, driver->datafile) &&
1877 !strequal(driver->helpfile, driver->configfile)) {
1878 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1879 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1880 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1881 driver_unix_convert(conn,new_name,&st);
1882 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
1883 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1884 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1885 new_name, old_name));
1886 *perr = WERR_ACCESS_DENIED;
1887 ver = -1;
1893 if (driver->dependentfiles) {
1894 for (i=0; *driver->dependentfiles[i]; i++) {
1895 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1896 !strequal(driver->dependentfiles[i], driver->datafile) &&
1897 !strequal(driver->dependentfiles[i], driver->configfile) &&
1898 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1899 int j;
1900 for (j=0; j < i; j++) {
1901 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1902 goto NextDriver;
1906 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1907 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1908 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1909 driver_unix_convert(conn,new_name,&st);
1910 if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
1911 OPENX_FILE_EXISTS_TRUNCATE|
1912 OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
1913 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1914 new_name, old_name));
1915 *perr = WERR_ACCESS_DENIED;
1916 ver = -1;
1920 NextDriver: ;
1924 close_cnum(conn, user->vuid);
1925 unbecome_user();
1927 return ver != -1 ? WERR_OK : WERR_UNKNOWN_PRINTER_DRIVER;
1930 /****************************************************************************
1931 ****************************************************************************/
1932 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1934 int len, buflen;
1935 const char *architecture;
1936 pstring directory;
1937 fstring temp_name;
1938 pstring key;
1939 uint8 *buf;
1940 int i, ret;
1941 TDB_DATA dbuf;
1943 architecture = get_short_archi(driver->environment);
1944 if (!architecture) {
1945 return (uint32)-1;
1948 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1949 * \\server is added in the rpc server layer.
1950 * It does make sense to NOT store the server's name in the printer TDB.
1953 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1955 /* .inf files do not always list a file for each of the four standard files.
1956 * Don't prepend a path to a null filename, or client claims:
1957 * "The server on which the printer resides does not have a suitable
1958 * <printer driver name> printer driver installed. Click OK if you
1959 * wish to install the driver on your local machine."
1961 if (strlen(driver->driverpath)) {
1962 fstrcpy(temp_name, driver->driverpath);
1963 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1966 if (strlen(driver->datafile)) {
1967 fstrcpy(temp_name, driver->datafile);
1968 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1971 if (strlen(driver->configfile)) {
1972 fstrcpy(temp_name, driver->configfile);
1973 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1976 if (strlen(driver->helpfile)) {
1977 fstrcpy(temp_name, driver->helpfile);
1978 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1981 if (driver->dependentfiles) {
1982 for (i=0; *driver->dependentfiles[i]; i++) {
1983 fstrcpy(temp_name, driver->dependentfiles[i]);
1984 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1988 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1990 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1992 buf = NULL;
1993 len = buflen = 0;
1995 again:
1996 len = 0;
1997 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1998 driver->cversion,
1999 driver->name,
2000 driver->environment,
2001 driver->driverpath,
2002 driver->datafile,
2003 driver->configfile,
2004 driver->helpfile,
2005 driver->monitorname,
2006 driver->defaultdatatype);
2008 if (driver->dependentfiles) {
2009 for (i=0; *driver->dependentfiles[i]; i++) {
2010 len += tdb_pack(buf+len, buflen-len, "f",
2011 driver->dependentfiles[i]);
2015 if (len != buflen) {
2016 buf = (uint8 *)SMB_REALLOC(buf, len);
2017 if (!buf) {
2018 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2019 ret = -1;
2020 goto done;
2022 buflen = len;
2023 goto again;
2026 dbuf.dptr = buf;
2027 dbuf.dsize = len;
2029 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2031 done:
2032 if (ret)
2033 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2035 SAFE_FREE(buf);
2036 return ret;
2039 /****************************************************************************
2040 ****************************************************************************/
2041 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
2043 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
2045 ZERO_STRUCT(info3);
2046 info3.cversion = driver->version;
2047 fstrcpy(info3.name,driver->name);
2048 fstrcpy(info3.environment,driver->environment);
2049 fstrcpy(info3.driverpath,driver->driverpath);
2050 fstrcpy(info3.datafile,driver->datafile);
2051 fstrcpy(info3.configfile,driver->configfile);
2052 fstrcpy(info3.helpfile,driver->helpfile);
2053 fstrcpy(info3.monitorname,driver->monitorname);
2054 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
2055 info3.dependentfiles = driver->dependentfiles;
2057 return add_a_printer_driver_3(&info3);
2061 /****************************************************************************
2062 ****************************************************************************/
2063 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
2065 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
2067 ZERO_STRUCT(info);
2069 fstrcpy(info.name, driver);
2070 fstrcpy(info.defaultdatatype, "RAW");
2072 fstrcpy(info.driverpath, "");
2073 fstrcpy(info.datafile, "");
2074 fstrcpy(info.configfile, "");
2075 fstrcpy(info.helpfile, "");
2077 if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
2078 return WERR_NOMEM;
2080 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
2081 fstrcpy(info.dependentfiles[0], "");
2083 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
2084 if (!*info_ptr) {
2085 SAFE_FREE(info.dependentfiles);
2086 return WERR_NOMEM;
2089 return WERR_OK;
2092 /****************************************************************************
2093 ****************************************************************************/
2094 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
2096 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
2097 TDB_DATA dbuf;
2098 const char *architecture;
2099 int len = 0;
2100 int i;
2101 pstring key;
2103 ZERO_STRUCT(driver);
2105 architecture = get_short_archi(arch);
2106 if ( !architecture ) {
2107 return WERR_UNKNOWN_PRINTER_DRIVER;
2110 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2112 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2113 version = 0;
2115 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2117 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
2119 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2120 if (!dbuf.dptr)
2121 return WERR_UNKNOWN_PRINTER_DRIVER;
2123 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2124 &driver.cversion,
2125 driver.name,
2126 driver.environment,
2127 driver.driverpath,
2128 driver.datafile,
2129 driver.configfile,
2130 driver.helpfile,
2131 driver.monitorname,
2132 driver.defaultdatatype);
2134 i=0;
2135 while (len < dbuf.dsize) {
2136 driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
2137 if ( !driver.dependentfiles ) {
2138 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2139 break;
2142 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2143 &driver.dependentfiles[i]);
2144 i++;
2147 if ( driver.dependentfiles )
2148 fstrcpy( driver.dependentfiles[i], "" );
2150 SAFE_FREE(dbuf.dptr);
2152 if (len != dbuf.dsize) {
2153 SAFE_FREE(driver.dependentfiles);
2155 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
2158 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
2159 if (!*info_ptr) {
2160 SAFE_FREE(driver.dependentfiles);
2161 return WERR_NOMEM;
2164 return WERR_OK;
2167 /****************************************************************************
2168 Debugging function, dump at level 6 the struct in the logs.
2169 ****************************************************************************/
2171 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2173 uint32 result;
2174 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2175 int i;
2177 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
2179 switch (level)
2181 case 3:
2183 if (driver.info_3 == NULL)
2184 result=5;
2185 else {
2186 info3=driver.info_3;
2188 DEBUGADD(20,("version:[%d]\n", info3->cversion));
2189 DEBUGADD(20,("name:[%s]\n", info3->name));
2190 DEBUGADD(20,("environment:[%s]\n", info3->environment));
2191 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
2192 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
2193 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
2194 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
2195 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
2196 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
2198 for (i=0; info3->dependentfiles &&
2199 *info3->dependentfiles[i]; i++) {
2200 DEBUGADD(20,("dependentfile:[%s]\n",
2201 info3->dependentfiles[i]));
2203 result=0;
2205 break;
2207 default:
2208 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
2209 result=1;
2210 break;
2213 return result;
2216 /****************************************************************************
2217 ****************************************************************************/
2218 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2220 int len = 0;
2222 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2224 if (!nt_devmode)
2225 return len;
2227 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2228 nt_devmode->devicename,
2229 nt_devmode->formname,
2231 nt_devmode->specversion,
2232 nt_devmode->driverversion,
2233 nt_devmode->size,
2234 nt_devmode->driverextra,
2235 nt_devmode->orientation,
2236 nt_devmode->papersize,
2237 nt_devmode->paperlength,
2238 nt_devmode->paperwidth,
2239 nt_devmode->scale,
2240 nt_devmode->copies,
2241 nt_devmode->defaultsource,
2242 nt_devmode->printquality,
2243 nt_devmode->color,
2244 nt_devmode->duplex,
2245 nt_devmode->yresolution,
2246 nt_devmode->ttoption,
2247 nt_devmode->collate,
2248 nt_devmode->logpixels,
2250 nt_devmode->fields,
2251 nt_devmode->bitsperpel,
2252 nt_devmode->pelswidth,
2253 nt_devmode->pelsheight,
2254 nt_devmode->displayflags,
2255 nt_devmode->displayfrequency,
2256 nt_devmode->icmmethod,
2257 nt_devmode->icmintent,
2258 nt_devmode->mediatype,
2259 nt_devmode->dithertype,
2260 nt_devmode->reserved1,
2261 nt_devmode->reserved2,
2262 nt_devmode->panningwidth,
2263 nt_devmode->panningheight,
2264 nt_devmode->nt_dev_private);
2267 if (nt_devmode->nt_dev_private) {
2268 len += tdb_pack(buf+len, buflen-len, "B",
2269 nt_devmode->driverextra,
2270 nt_devmode->nt_dev_private);
2273 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2275 return len;
2278 /****************************************************************************
2279 Pack all values in all printer keys
2280 ***************************************************************************/
2282 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2284 int len = 0;
2285 int i, j;
2286 REGISTRY_VALUE *val;
2287 REGVAL_CTR *val_ctr;
2288 pstring path;
2289 int num_values;
2291 if ( !data )
2292 return 0;
2294 /* loop over all keys */
2296 for ( i=0; i<data->num_keys; i++ ) {
2297 val_ctr = data->keys[i].values;
2298 num_values = regval_ctr_numvals( val_ctr );
2300 /* pack the keyname followed by a empty value */
2302 len += tdb_pack(buf+len, buflen-len, "pPdB",
2303 &data->keys[i].name,
2304 data->keys[i].name,
2305 REG_NONE,
2307 NULL);
2309 /* now loop over all values */
2311 for ( j=0; j<num_values; j++ ) {
2312 /* pathname should be stored as <key>\<value> */
2314 val = regval_ctr_specific_value( val_ctr, j );
2315 pstrcpy( path, data->keys[i].name );
2316 pstrcat( path, "\\" );
2317 pstrcat( path, regval_name(val) );
2319 len += tdb_pack(buf+len, buflen-len, "pPdB",
2320 val,
2321 path,
2322 regval_type(val),
2323 regval_size(val),
2324 regval_data_p(val) );
2326 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2331 /* terminator */
2333 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2335 return len;
2339 /****************************************************************************
2340 Delete a printer - this just deletes the printer info file, any open
2341 handles are not affected.
2342 ****************************************************************************/
2344 uint32 del_a_printer(const char *sharename)
2346 TDB_DATA kbuf;
2347 pstring printdb_path;
2349 kbuf = make_printer_tdbkey( sharename );
2350 tdb_delete(tdb_printers, kbuf);
2352 kbuf= make_printers_secdesc_tdbkey( sharename );
2353 tdb_delete(tdb_printers, kbuf);
2355 close_all_print_db();
2357 if (geteuid() == 0) {
2358 pstrcpy(printdb_path, lock_path("printing/"));
2359 pstrcat(printdb_path, sharename);
2360 pstrcat(printdb_path, ".tdb");
2362 unlink(printdb_path);
2365 return 0;
2368 /****************************************************************************
2369 ****************************************************************************/
2370 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2372 uint8 *buf;
2373 int buflen, len;
2374 WERROR ret;
2375 TDB_DATA kbuf, dbuf;
2378 * in addprinter: no servername and the printer is the name
2379 * in setprinter: servername is \\server
2380 * and printer is \\server\\printer
2382 * Samba manages only local printers.
2383 * we currently don't support things like i
2384 * path=\\other_server\printer
2386 * We only store the printername, not \\server\printername
2389 if ( info->servername[0] != '\0' ) {
2390 trim_string(info->printername, info->servername, NULL);
2391 trim_char(info->printername, '\\', '\0');
2392 info->servername[0]='\0';
2396 * JFM: one day I'll forget.
2397 * below that's info->portname because that's the SAMBA sharename
2398 * and I made NT 'thinks' it's the portname
2399 * the info->sharename is the thing you can name when you add a printer
2400 * that's the short-name when you create shared printer for 95/98
2401 * So I've made a limitation in SAMBA: you can only have 1 printer model
2402 * behind a SAMBA share.
2405 buf = NULL;
2406 buflen = 0;
2408 again:
2409 len = 0;
2410 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2411 info->attributes,
2412 info->priority,
2413 info->default_priority,
2414 info->starttime,
2415 info->untiltime,
2416 info->status,
2417 info->cjobs,
2418 info->averageppm,
2419 info->changeid,
2420 info->c_setprinter,
2421 info->setuptime,
2422 info->servername,
2423 info->printername,
2424 info->sharename,
2425 info->portname,
2426 info->drivername,
2427 info->comment,
2428 info->location,
2429 info->sepfile,
2430 info->printprocessor,
2431 info->datatype,
2432 info->parameters);
2434 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2436 len += pack_values( info->data, buf+len, buflen-len );
2438 if (buflen != len) {
2439 buf = (uint8 *)SMB_REALLOC(buf, len);
2440 if (!buf) {
2441 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2442 ret = WERR_NOMEM;
2443 goto done;
2445 buflen = len;
2446 goto again;
2450 kbuf = make_printer_tdbkey( info->sharename );
2452 dbuf.dptr = buf;
2453 dbuf.dsize = len;
2455 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2457 done:
2458 if (!W_ERROR_IS_OK(ret))
2459 DEBUG(8, ("error updating printer to tdb on disk\n"));
2461 SAFE_FREE(buf);
2463 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2464 info->sharename, info->drivername, info->portname, len));
2466 return ret;
2470 /****************************************************************************
2471 Malloc and return an NT devicemode.
2472 ****************************************************************************/
2474 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2477 char adevice[MAXDEVICENAME];
2478 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2480 if (nt_devmode == NULL) {
2481 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2482 return NULL;
2485 ZERO_STRUCTP(nt_devmode);
2487 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2488 fstrcpy(nt_devmode->devicename, adevice);
2490 fstrcpy(nt_devmode->formname, "Letter");
2492 nt_devmode->specversion = 0x0401;
2493 nt_devmode->driverversion = 0x0400;
2494 nt_devmode->size = 0x00DC;
2495 nt_devmode->driverextra = 0x0000;
2496 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2497 DEFAULTSOURCE | COPIES | SCALE |
2498 PAPERSIZE | ORIENTATION;
2499 nt_devmode->orientation = 1;
2500 nt_devmode->papersize = PAPER_LETTER;
2501 nt_devmode->paperlength = 0;
2502 nt_devmode->paperwidth = 0;
2503 nt_devmode->scale = 0x64;
2504 nt_devmode->copies = 1;
2505 nt_devmode->defaultsource = BIN_FORMSOURCE;
2506 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2507 nt_devmode->color = COLOR_MONOCHROME;
2508 nt_devmode->duplex = DUP_SIMPLEX;
2509 nt_devmode->yresolution = 0;
2510 nt_devmode->ttoption = TT_SUBDEV;
2511 nt_devmode->collate = COLLATE_FALSE;
2512 nt_devmode->icmmethod = 0;
2513 nt_devmode->icmintent = 0;
2514 nt_devmode->mediatype = 0;
2515 nt_devmode->dithertype = 0;
2517 /* non utilisés par un driver d'imprimante */
2518 nt_devmode->logpixels = 0;
2519 nt_devmode->bitsperpel = 0;
2520 nt_devmode->pelswidth = 0;
2521 nt_devmode->pelsheight = 0;
2522 nt_devmode->displayflags = 0;
2523 nt_devmode->displayfrequency = 0;
2524 nt_devmode->reserved1 = 0;
2525 nt_devmode->reserved2 = 0;
2526 nt_devmode->panningwidth = 0;
2527 nt_devmode->panningheight = 0;
2529 nt_devmode->nt_dev_private = NULL;
2530 return nt_devmode;
2533 /****************************************************************************
2534 Deepcopy an NT devicemode.
2535 ****************************************************************************/
2537 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2539 NT_DEVICEMODE *new_nt_devicemode = NULL;
2541 if ( !nt_devicemode )
2542 return NULL;
2544 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2545 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2546 return NULL;
2549 new_nt_devicemode->nt_dev_private = NULL;
2550 if (nt_devicemode->nt_dev_private != NULL) {
2551 if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
2552 SAFE_FREE(new_nt_devicemode);
2553 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2554 return NULL;
2558 return new_nt_devicemode;
2561 /****************************************************************************
2562 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2563 ****************************************************************************/
2565 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2567 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2569 if(nt_devmode == NULL)
2570 return;
2572 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2574 SAFE_FREE(nt_devmode->nt_dev_private);
2575 SAFE_FREE(*devmode_ptr);
2578 /****************************************************************************
2579 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2580 ****************************************************************************/
2582 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2584 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2586 if ( !info )
2587 return;
2589 free_nt_devicemode(&info->devmode);
2591 TALLOC_FREE( *info_ptr );
2595 /****************************************************************************
2596 ****************************************************************************/
2597 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2599 int len = 0;
2600 int extra_len = 0;
2601 NT_DEVICEMODE devmode;
2603 ZERO_STRUCT(devmode);
2605 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2607 if (!*nt_devmode) return len;
2609 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2610 devmode.devicename,
2611 devmode.formname,
2613 &devmode.specversion,
2614 &devmode.driverversion,
2615 &devmode.size,
2616 &devmode.driverextra,
2617 &devmode.orientation,
2618 &devmode.papersize,
2619 &devmode.paperlength,
2620 &devmode.paperwidth,
2621 &devmode.scale,
2622 &devmode.copies,
2623 &devmode.defaultsource,
2624 &devmode.printquality,
2625 &devmode.color,
2626 &devmode.duplex,
2627 &devmode.yresolution,
2628 &devmode.ttoption,
2629 &devmode.collate,
2630 &devmode.logpixels,
2632 &devmode.fields,
2633 &devmode.bitsperpel,
2634 &devmode.pelswidth,
2635 &devmode.pelsheight,
2636 &devmode.displayflags,
2637 &devmode.displayfrequency,
2638 &devmode.icmmethod,
2639 &devmode.icmintent,
2640 &devmode.mediatype,
2641 &devmode.dithertype,
2642 &devmode.reserved1,
2643 &devmode.reserved2,
2644 &devmode.panningwidth,
2645 &devmode.panningheight,
2646 &devmode.nt_dev_private);
2648 if (devmode.nt_dev_private) {
2649 /* the len in tdb_unpack is an int value and
2650 * devmode.driverextra is only a short
2652 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2653 devmode.driverextra=(uint16)extra_len;
2655 /* check to catch an invalid TDB entry so we don't segfault */
2656 if (devmode.driverextra == 0) {
2657 devmode.nt_dev_private = NULL;
2661 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2662 if (!*nt_devmode) {
2663 SAFE_FREE(devmode.nt_dev_private);
2664 return -1;
2667 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2668 if (devmode.nt_dev_private)
2669 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2671 return len;
2674 /****************************************************************************
2675 Allocate and initialize a new slot.
2676 ***************************************************************************/
2678 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2680 NT_PRINTER_KEY *d;
2681 int key_index;
2683 if ( !name || !data )
2684 return -1;
2686 /* allocate another slot in the NT_PRINTER_KEY array */
2688 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2689 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2690 return -1;
2693 data->keys = d;
2695 key_index = data->num_keys;
2697 /* initialze new key */
2699 data->keys[key_index].name = talloc_strdup( data, name );
2701 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
2702 return -1;
2704 data->num_keys++;
2706 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2708 return key_index;
2711 /****************************************************************************
2712 search for a registry key name in the existing printer data
2713 ***************************************************************************/
2715 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2717 int i;
2719 for ( i=0; i<data->num_keys; i++ ) {
2720 if ( strequal( data->keys[i].name, name ) ) {
2722 /* cleanup memory */
2724 TALLOC_FREE( data->keys[i].name );
2725 TALLOC_FREE( data->keys[i].values );
2727 /* if not the end of the array, move remaining elements down one slot */
2729 data->num_keys--;
2730 if ( data->num_keys && (i < data->num_keys) )
2731 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2733 break;
2738 return data->num_keys;
2741 /****************************************************************************
2742 search for a registry key name in the existing printer data
2743 ***************************************************************************/
2745 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2747 int key_index = -1;
2748 int i;
2750 if ( !data || !name )
2751 return -1;
2753 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2755 /* loop over all existing keys */
2757 for ( i=0; i<data->num_keys; i++ ) {
2758 if ( strequal(data->keys[i].name, name) ) {
2759 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2760 key_index = i;
2761 break;
2766 return key_index;
2769 /****************************************************************************
2770 ***************************************************************************/
2772 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2774 int i, j;
2775 int key_len;
2776 int num_subkeys = 0;
2777 char *p;
2778 fstring *subkeys_ptr = NULL;
2779 fstring subkeyname;
2781 *subkeys = NULL;
2783 if ( !data )
2784 return 0;
2786 if ( !key )
2787 return -1;
2789 /* special case of asking for the top level printer data registry key names */
2791 if ( strlen(key) == 0 ) {
2792 for ( i=0; i<data->num_keys; i++ ) {
2794 /* found a match, so allocate space and copy the name */
2796 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2797 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2798 num_subkeys+1));
2799 return -1;
2802 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
2803 num_subkeys++;
2806 goto done;
2809 /* asking for the subkeys of some key */
2810 /* subkey paths are stored in the key name using '\' as the delimiter */
2812 for ( i=0; i<data->num_keys; i++ ) {
2813 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2815 /* if we found the exact key, then break */
2816 key_len = strlen( key );
2817 if ( strlen(data->keys[i].name) == key_len )
2818 break;
2820 /* get subkey path */
2822 p = data->keys[i].name + key_len;
2823 if ( *p == '\\' )
2824 p++;
2825 fstrcpy( subkeyname, p );
2826 if ( (p = strchr( subkeyname, '\\' )) )
2827 *p = '\0';
2829 /* don't add a key more than once */
2831 for ( j=0; j<num_subkeys; j++ ) {
2832 if ( strequal( subkeys_ptr[j], subkeyname ) )
2833 break;
2836 if ( j != num_subkeys )
2837 continue;
2839 /* found a match, so allocate space and copy the name */
2841 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
2842 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2843 num_subkeys+1));
2844 return 0;
2847 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2848 num_subkeys++;
2853 /* return error if the key was not found */
2855 if ( i == data->num_keys ) {
2856 SAFE_FREE(subkeys_ptr);
2857 return -1;
2860 done:
2861 /* tag off the end */
2863 if (num_subkeys)
2864 fstrcpy(subkeys_ptr[num_subkeys], "" );
2866 *subkeys = subkeys_ptr;
2868 return num_subkeys;
2871 #ifdef HAVE_ADS
2872 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2873 const char *sz)
2875 smb_ucs2_t conv_str[1024];
2876 size_t str_size;
2878 regval_ctr_delvalue(ctr, val_name);
2879 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2880 STR_TERMINATE | STR_NOALIGN);
2881 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2882 (char *) conv_str, str_size);
2885 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2886 uint32 dword)
2888 regval_ctr_delvalue(ctr, val_name);
2889 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2890 (char *) &dword, sizeof(dword));
2893 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2894 BOOL b)
2896 uint8 bin_bool = (b ? 1 : 0);
2897 regval_ctr_delvalue(ctr, val_name);
2898 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2899 (char *) &bin_bool, sizeof(bin_bool));
2902 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2903 const char *multi_sz)
2905 smb_ucs2_t *conv_strs = NULL;
2906 size_t str_size;
2908 /* a multi-sz has to have a null string terminator, i.e., the last
2909 string must be followed by two nulls */
2910 str_size = strlen(multi_sz) + 2;
2911 conv_strs = SMB_CALLOC_ARRAY(smb_ucs2_t, str_size);
2912 if (!conv_strs) {
2913 return;
2916 /* Change to byte units. */
2917 str_size *= sizeof(smb_ucs2_t);
2918 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2919 STR_TERMINATE | STR_NOALIGN);
2921 regval_ctr_delvalue(ctr, val_name);
2922 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2923 (char *) conv_strs, str_size);
2924 safe_free(conv_strs);
2928 /****************************************************************************
2929 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2931 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2932 * @return BOOL indicating success or failure
2933 ***************************************************************************/
2935 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2937 REGVAL_CTR *ctr = NULL;
2938 fstring longname;
2939 fstring dnssuffix;
2940 char *allocated_string = NULL;
2941 const char *ascii_str;
2942 int i;
2944 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2945 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
2946 ctr = info2->data->keys[i].values;
2948 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2949 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2951 /* we make the assumption that the netbios name is the same
2952 as the DNS name sinc ethe former will be what we used to
2953 join the domain */
2955 if ( get_mydnsdomname( dnssuffix ) )
2956 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
2957 else
2958 fstrcpy( longname, global_myname() );
2960 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2962 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2963 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2964 SAFE_FREE(allocated_string);
2966 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2967 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2968 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2969 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2970 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2971 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2972 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2973 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2974 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2976 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2977 (info2->attributes &
2978 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2980 switch (info2->attributes & 0x3) {
2981 case 0:
2982 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2983 break;
2984 case 1:
2985 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2986 break;
2987 case 2:
2988 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2989 break;
2990 default:
2991 ascii_str = "unknown";
2993 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2995 return True;
2998 /*****************************************************************
2999 ****************************************************************/
3001 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3002 struct GUID guid)
3004 int i;
3005 REGVAL_CTR *ctr=NULL;
3006 UNISTR2 unistr_guid;
3008 /* find the DsSpooler key */
3009 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3010 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3011 ctr = info2->data->keys[i].values;
3013 regval_ctr_delvalue(ctr, "objectGUID");
3015 /* We used to store this as a REG_BINARY but that causes
3016 Vista to whine */
3018 ZERO_STRUCT( unistr_guid );
3019 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3020 UNI_STR_TERMINATE );
3022 regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
3023 (char *)unistr_guid.buffer,
3024 unistr_guid.uni_max_len*2);
3028 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3029 NT_PRINTER_INFO_LEVEL *printer)
3031 ADS_STATUS ads_rc;
3032 LDAPMessage *res;
3033 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3034 char *srv_dn_utf8, **srv_cn_utf8;
3035 TALLOC_CTX *ctx;
3036 ADS_MODLIST mods;
3037 const char *attrs[] = {"objectGUID", NULL};
3038 struct GUID guid;
3039 WERROR win_rc = WERR_OK;
3041 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3043 /* figure out where to publish */
3044 ads_find_machine_acct(ads, &res, global_myname());
3046 /* We use ldap_get_dn here as we need the answer
3047 * in utf8 to call ldap_explode_dn(). JRA. */
3049 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3050 if (!srv_dn_utf8) {
3051 ads_destroy(&ads);
3052 return WERR_SERVER_UNAVAILABLE;
3054 ads_msgfree(ads, res);
3055 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3056 if (!srv_cn_utf8) {
3057 ldap_memfree(srv_dn_utf8);
3058 ads_destroy(&ads);
3059 return WERR_SERVER_UNAVAILABLE;
3061 /* Now convert to CH_UNIX. */
3062 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
3063 ldap_memfree(srv_dn_utf8);
3064 ldap_memfree(srv_cn_utf8);
3065 ads_destroy(&ads);
3066 return WERR_SERVER_UNAVAILABLE;
3068 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
3069 ldap_memfree(srv_dn_utf8);
3070 ldap_memfree(srv_cn_utf8);
3071 ads_destroy(&ads);
3072 SAFE_FREE(srv_dn);
3073 return WERR_SERVER_UNAVAILABLE;
3076 ldap_memfree(srv_dn_utf8);
3077 ldap_memfree(srv_cn_utf8);
3079 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3080 if (!srv_cn_escaped) {
3081 SAFE_FREE(srv_cn_0);
3082 ldap_memfree(srv_dn_utf8);
3083 ads_destroy(&ads);
3084 return WERR_SERVER_UNAVAILABLE;
3086 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3087 if (!sharename_escaped) {
3088 SAFE_FREE(srv_cn_escaped);
3089 SAFE_FREE(srv_cn_0);
3090 ldap_memfree(srv_dn_utf8);
3091 ads_destroy(&ads);
3092 return WERR_SERVER_UNAVAILABLE;
3096 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3098 SAFE_FREE(srv_dn);
3099 SAFE_FREE(srv_cn_0);
3100 SAFE_FREE(srv_cn_escaped);
3101 SAFE_FREE(sharename_escaped);
3103 /* build the ads mods */
3104 ctx = talloc_init("nt_printer_publish_ads");
3105 if (ctx == NULL) {
3106 SAFE_FREE(prt_dn);
3107 return WERR_NOMEM;
3110 mods = ads_init_mods(ctx);
3112 if (mods == NULL) {
3113 SAFE_FREE(prt_dn);
3114 talloc_destroy(ctx);
3115 return WERR_NOMEM;
3118 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3119 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3120 printer->info_2->sharename);
3122 /* publish it */
3123 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3124 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
3125 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3127 if (!ADS_ERR_OK(ads_rc))
3128 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3130 talloc_destroy(ctx);
3132 /* retreive the guid and store it locally */
3133 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3134 ZERO_STRUCT(guid);
3135 ads_pull_guid(ads, res, &guid);
3136 ads_msgfree(ads, res);
3137 store_printer_guid(printer->info_2, guid);
3138 win_rc = mod_a_printer(printer, 2);
3141 SAFE_FREE(prt_dn);
3142 return win_rc;
3145 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3146 NT_PRINTER_INFO_LEVEL *printer)
3148 ADS_STATUS ads_rc;
3149 LDAPMessage *res;
3150 char *prt_dn = NULL;
3152 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3154 /* remove the printer from the directory */
3155 ads_rc = ads_find_printer_on_server(ads, &res,
3156 printer->info_2->sharename, global_myname());
3158 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
3159 prt_dn = ads_get_dn(ads, res);
3160 if (!prt_dn) {
3161 ads_msgfree(ads, res);
3162 return WERR_NOMEM;
3164 ads_rc = ads_del_dn(ads, prt_dn);
3165 ads_memfree(ads, prt_dn);
3168 ads_msgfree(ads, res);
3169 return WERR_OK;
3172 /****************************************************************************
3173 * Publish a printer in the directory
3175 * @param snum describing printer service
3176 * @return WERROR indicating status of publishing
3177 ***************************************************************************/
3179 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3181 ADS_STATUS ads_rc;
3182 ADS_STRUCT *ads = NULL;
3183 NT_PRINTER_INFO_LEVEL *printer = NULL;
3184 WERROR win_rc;
3186 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3187 if (!W_ERROR_IS_OK(win_rc))
3188 goto done;
3190 switch (action) {
3191 case SPOOL_DS_PUBLISH:
3192 case SPOOL_DS_UPDATE:
3193 /* set the DsSpooler info and attributes */
3194 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3195 win_rc = WERR_NOMEM;
3196 goto done;
3199 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3200 break;
3201 case SPOOL_DS_UNPUBLISH:
3202 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3203 break;
3204 default:
3205 win_rc = WERR_NOT_SUPPORTED;
3206 goto done;
3209 win_rc = mod_a_printer(printer, 2);
3210 if (!W_ERROR_IS_OK(win_rc)) {
3211 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3212 goto done;
3215 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3216 if (!ads) {
3217 DEBUG(3, ("ads_init() failed\n"));
3218 win_rc = WERR_SERVER_UNAVAILABLE;
3219 goto done;
3221 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3222 SAFE_FREE(ads->auth.password);
3223 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3224 NULL, NULL);
3226 /* ads_connect() will find the DC for us */
3227 ads_rc = ads_connect(ads);
3228 if (!ADS_ERR_OK(ads_rc)) {
3229 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3230 win_rc = WERR_ACCESS_DENIED;
3231 goto done;
3234 switch (action) {
3235 case SPOOL_DS_PUBLISH:
3236 case SPOOL_DS_UPDATE:
3237 win_rc = nt_printer_publish_ads(ads, printer);
3238 break;
3239 case SPOOL_DS_UNPUBLISH:
3240 win_rc = nt_printer_unpublish_ads(ads, printer);
3241 break;
3244 done:
3245 free_a_printer(&printer, 2);
3246 ads_destroy(&ads);
3247 return win_rc;
3250 WERROR check_published_printers(void)
3252 ADS_STATUS ads_rc;
3253 ADS_STRUCT *ads = NULL;
3254 int snum;
3255 int n_services = lp_numservices();
3256 NT_PRINTER_INFO_LEVEL *printer = NULL;
3258 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3259 if (!ads) {
3260 DEBUG(3, ("ads_init() failed\n"));
3261 return WERR_SERVER_UNAVAILABLE;
3263 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3264 SAFE_FREE(ads->auth.password);
3265 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3266 NULL, NULL);
3268 /* ads_connect() will find the DC for us */
3269 ads_rc = ads_connect(ads);
3270 if (!ADS_ERR_OK(ads_rc)) {
3271 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3272 ads_destroy(&ads);
3273 ads_kdestroy("MEMORY:prtpub_cache");
3274 return WERR_ACCESS_DENIED;
3277 for (snum = 0; snum < n_services; snum++) {
3278 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3279 continue;
3281 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3282 lp_servicename(snum))) &&
3283 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3284 nt_printer_publish_ads(ads, printer);
3286 free_a_printer(&printer, 2);
3289 ads_destroy(&ads);
3290 ads_kdestroy("MEMORY:prtpub_cache");
3291 return WERR_OK;
3294 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3295 struct GUID *guid)
3297 NT_PRINTER_INFO_LEVEL *printer = NULL;
3298 REGVAL_CTR *ctr;
3299 REGISTRY_VALUE *guid_val;
3300 WERROR win_rc;
3301 int i;
3302 BOOL ret = False;
3304 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3306 if (!W_ERROR_IS_OK(win_rc) ||
3307 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3308 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3309 !(ctr = printer->info_2->data->keys[i].values) ||
3310 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3312 free_a_printer(&printer, 2);
3313 return False;
3316 /* fetching printer guids really ought to be a separate function. */
3318 if ( guid ) {
3319 fstring guid_str;
3321 /* We used to store the guid as REG_BINARY, then swapped
3322 to REG_SZ for Vista compatibility so check for both */
3324 switch ( regval_type(guid_val) ){
3325 case REG_SZ:
3326 rpcstr_pull( guid_str, regval_data_p(guid_val),
3327 sizeof(guid_str)-1, -1, STR_TERMINATE );
3328 ret = smb_string_to_uuid( guid_str, guid );
3329 break;
3330 case REG_BINARY:
3331 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3332 ret = False;
3333 break;
3335 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3336 break;
3337 default:
3338 DEBUG(0,("is_printer_published: GUID value stored as "
3339 "invaluid type (%d)\n", regval_type(guid_val) ));
3340 break;
3344 free_a_printer(&printer, 2);
3345 return ret;
3347 #else
3348 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3350 return WERR_OK;
3353 WERROR check_published_printers(void)
3355 return WERR_OK;
3358 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
3359 struct GUID *guid)
3361 return False;
3363 #endif /* HAVE_ADS */
3365 /****************************************************************************
3366 ***************************************************************************/
3368 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3370 NT_PRINTER_DATA *data;
3371 int i;
3372 int removed_keys = 0;
3373 int empty_slot;
3375 data = p2->data;
3376 empty_slot = data->num_keys;
3378 if ( !key )
3379 return WERR_INVALID_PARAM;
3381 /* remove all keys */
3383 if ( !strlen(key) ) {
3385 TALLOC_FREE( data );
3387 p2->data = NULL;
3389 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3390 p2->printername ));
3392 return WERR_OK;
3395 /* remove a specific key (and all subkeys) */
3397 for ( i=0; i<data->num_keys; i++ ) {
3398 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3399 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3400 data->keys[i].name));
3402 TALLOC_FREE( data->keys[i].name );
3403 TALLOC_FREE( data->keys[i].values );
3405 /* mark the slot as empty */
3407 ZERO_STRUCTP( &data->keys[i] );
3411 /* find the first empty slot */
3413 for ( i=0; i<data->num_keys; i++ ) {
3414 if ( !data->keys[i].name ) {
3415 empty_slot = i;
3416 removed_keys++;
3417 break;
3421 if ( i == data->num_keys )
3422 /* nothing was removed */
3423 return WERR_INVALID_PARAM;
3425 /* move everything down */
3427 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3428 if ( data->keys[i].name ) {
3429 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3430 ZERO_STRUCTP( &data->keys[i] );
3431 empty_slot++;
3432 removed_keys++;
3436 /* update count */
3438 data->num_keys -= removed_keys;
3440 /* sanity check to see if anything is left */
3442 if ( !data->num_keys ) {
3443 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3445 SAFE_FREE( data->keys );
3446 ZERO_STRUCTP( data );
3449 return WERR_OK;
3452 /****************************************************************************
3453 ***************************************************************************/
3455 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3457 WERROR result = WERR_OK;
3458 int key_index;
3460 /* we must have names on non-zero length */
3462 if ( !key || !*key|| !value || !*value )
3463 return WERR_INVALID_NAME;
3465 /* find the printer key first */
3467 key_index = lookup_printerkey( p2->data, key );
3468 if ( key_index == -1 )
3469 return WERR_OK;
3471 /* make sure the value exists so we can return the correct error code */
3473 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3474 return WERR_BADFILE;
3476 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3478 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3479 key, value ));
3481 return result;
3484 /****************************************************************************
3485 ***************************************************************************/
3487 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3488 uint32 type, uint8 *data, int real_len )
3490 WERROR result = WERR_OK;
3491 int key_index;
3493 /* we must have names on non-zero length */
3495 if ( !key || !*key|| !value || !*value )
3496 return WERR_INVALID_NAME;
3498 /* find the printer key first */
3500 key_index = lookup_printerkey( p2->data, key );
3501 if ( key_index == -1 )
3502 key_index = add_new_printer_key( p2->data, key );
3504 if ( key_index == -1 )
3505 return WERR_NOMEM;
3507 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3508 type, (const char *)data, real_len );
3510 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3511 key, value, type, real_len ));
3513 return result;
3516 /****************************************************************************
3517 ***************************************************************************/
3519 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3521 int key_index;
3523 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3524 return NULL;
3526 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3527 key, value ));
3529 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3532 /****************************************************************************
3533 Unpack a list of registry values frem the TDB
3534 ***************************************************************************/
3536 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3538 int len = 0;
3539 uint32 type;
3540 pstring string, valuename, keyname;
3541 char *str;
3542 int size;
3543 uint8 *data_p;
3544 REGISTRY_VALUE *regval_p;
3545 int key_index;
3547 /* add the "PrinterDriverData" key first for performance reasons */
3549 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3551 /* loop and unpack the rest of the registry values */
3553 while ( True ) {
3555 /* check to see if there are any more registry values */
3557 regval_p = NULL;
3558 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3559 if ( !regval_p )
3560 break;
3562 /* unpack the next regval */
3564 len += tdb_unpack(buf+len, buflen-len, "fdB",
3565 string,
3566 &type,
3567 &size,
3568 &data_p);
3570 /* lookup for subkey names which have a type of REG_NONE */
3571 /* there's no data with this entry */
3573 if ( type == REG_NONE ) {
3574 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3575 add_new_printer_key( printer_data, string );
3576 continue;
3580 * break of the keyname from the value name.
3581 * Valuenames can have embedded '\'s so be careful.
3582 * only support one level of keys. See the
3583 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3584 * -- jerry
3587 str = strchr_m( string, '\\');
3589 /* Put in "PrinterDriverData" is no key specified */
3591 if ( !str ) {
3592 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3593 pstrcpy( valuename, string );
3595 else {
3596 *str = '\0';
3597 pstrcpy( keyname, string );
3598 pstrcpy( valuename, str+1 );
3601 /* see if we need a new key */
3603 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3604 key_index = add_new_printer_key( printer_data, keyname );
3606 if ( key_index == -1 ) {
3607 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3608 keyname));
3609 break;
3612 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3614 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3615 Thanks to Martin Zielinski for the hint. */
3617 if ( type == REG_BINARY &&
3618 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3619 strequal( valuename, "objectGUID" ) )
3621 struct GUID guid;
3622 UNISTR2 unistr_guid;
3624 ZERO_STRUCT( unistr_guid );
3626 /* convert the GUID to a UNICODE string */
3628 memcpy( &guid, data_p, sizeof(struct GUID) );
3630 init_unistr2( &unistr_guid, smb_uuid_string_static(guid),
3631 UNI_STR_TERMINATE );
3633 regval_ctr_addvalue( printer_data->keys[key_index].values,
3634 valuename, REG_SZ,
3635 (const char *)unistr_guid.buffer,
3636 unistr_guid.uni_str_len*2 );
3638 } else {
3639 /* add the value */
3641 regval_ctr_addvalue( printer_data->keys[key_index].values,
3642 valuename, type, (const char *)data_p,
3643 size );
3647 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3651 return len;
3654 /****************************************************************************
3655 ***************************************************************************/
3657 static void map_to_os2_driver(fstring drivername)
3659 static BOOL initialised=False;
3660 static fstring last_from,last_to;
3661 char *mapfile = lp_os2_driver_map();
3662 char **lines = NULL;
3663 int numlines = 0;
3664 int i;
3666 if (!strlen(drivername))
3667 return;
3669 if (!*mapfile)
3670 return;
3672 if (!initialised) {
3673 *last_from = *last_to = 0;
3674 initialised = True;
3677 if (strequal(drivername,last_from)) {
3678 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3679 fstrcpy(drivername,last_to);
3680 return;
3683 lines = file_lines_load(mapfile, &numlines,0);
3684 if (numlines == 0 || lines == NULL) {
3685 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3686 SAFE_FREE(lines);
3687 return;
3690 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3692 for( i = 0; i < numlines; i++) {
3693 char *nt_name = lines[i];
3694 char *os2_name = strchr(nt_name,'=');
3696 if (!os2_name)
3697 continue;
3699 *os2_name++ = 0;
3701 while (isspace(*nt_name))
3702 nt_name++;
3704 if (!*nt_name || strchr("#;",*nt_name))
3705 continue;
3708 int l = strlen(nt_name);
3709 while (l && isspace(nt_name[l-1])) {
3710 nt_name[l-1] = 0;
3711 l--;
3715 while (isspace(*os2_name))
3716 os2_name++;
3719 int l = strlen(os2_name);
3720 while (l && isspace(os2_name[l-1])) {
3721 os2_name[l-1] = 0;
3722 l--;
3726 if (strequal(nt_name,drivername)) {
3727 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3728 fstrcpy(last_from,drivername);
3729 fstrcpy(last_to,os2_name);
3730 fstrcpy(drivername,os2_name);
3731 file_lines_free(lines);
3732 return;
3736 file_lines_free(lines);
3739 /****************************************************************************
3740 Get a default printer info 2 struct.
3741 ****************************************************************************/
3742 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
3744 int snum = lp_servicenumber(sharename);
3746 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3747 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3748 servername, sharename);
3749 fstrcpy(info->sharename, sharename);
3750 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3752 /* by setting the driver name to an empty string, a local NT admin
3753 can now run the **local** APW to install a local printer driver
3754 for a Samba shared printer in 2.2. Without this, drivers **must** be
3755 installed on the Samba server for NT clients --jerry */
3756 #if 0 /* JERRY --do not uncomment-- */
3757 if (!*info->drivername)
3758 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3759 #endif
3762 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3764 pstrcpy(info->comment, "");
3765 fstrcpy(info->printprocessor, "winprint");
3766 fstrcpy(info->datatype, "RAW");
3768 #ifdef HAVE_CUPS
3769 if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
3770 /* Pull the location and comment strings from cups if we don't
3771 already have one */
3772 if ( !strlen(info->location) || !strlen(info->comment) )
3773 cups_pull_comment_location( info );
3775 #endif
3777 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
3779 info->starttime = 0; /* Minutes since 12:00am GMT */
3780 info->untiltime = 0; /* Minutes since 12:00am GMT */
3781 info->priority = 1;
3782 info->default_priority = 1;
3783 info->setuptime = (uint32)time(NULL);
3786 * I changed this as I think it is better to have a generic
3787 * DEVMODE than to crash Win2k explorer.exe --jerry
3788 * See the HP Deskjet 990c Win2k drivers for an example.
3790 * However the default devmode appears to cause problems
3791 * with the HP CLJ 8500 PCL driver. Hence the addition of
3792 * the "default devmode" parameter --jerry 22/01/2002
3795 if (lp_default_devmode(snum)) {
3796 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
3797 goto fail;
3799 } else {
3800 info->devmode = NULL;
3803 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3804 goto fail;
3807 return WERR_OK;
3809 fail:
3810 if (info->devmode)
3811 free_nt_devicemode(&info->devmode);
3813 return WERR_ACCESS_DENIED;
3816 /****************************************************************************
3817 ****************************************************************************/
3818 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char *sharename)
3820 int len = 0;
3821 int snum = lp_servicenumber(sharename);
3822 TDB_DATA kbuf, dbuf;
3823 fstring printername;
3824 char adevice[MAXDEVICENAME];
3826 kbuf = make_printer_tdbkey( sharename );
3828 dbuf = tdb_fetch(tdb_printers, kbuf);
3829 if (!dbuf.dptr) {
3830 return get_a_printer_2_default(info, servername, sharename);
3833 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3834 &info->attributes,
3835 &info->priority,
3836 &info->default_priority,
3837 &info->starttime,
3838 &info->untiltime,
3839 &info->status,
3840 &info->cjobs,
3841 &info->averageppm,
3842 &info->changeid,
3843 &info->c_setprinter,
3844 &info->setuptime,
3845 info->servername,
3846 info->printername,
3847 info->sharename,
3848 info->portname,
3849 info->drivername,
3850 info->comment,
3851 info->location,
3852 info->sepfile,
3853 info->printprocessor,
3854 info->datatype,
3855 info->parameters);
3857 /* Samba has to have shared raw drivers. */
3858 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
3859 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3861 /* Restore the stripped strings. */
3862 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3864 if ( lp_force_printername(snum) ) {
3865 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3866 } else {
3867 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
3870 fstrcpy(info->printername, printername);
3872 #ifdef HAVE_CUPS
3873 if ( (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 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
3884 * Some client drivers freak out if there is a NULL devmode
3885 * (probably the driver is not checking before accessing
3886 * the devmode pointer) --jerry
3888 * See comments in get_a_printer_2_default()
3891 if (lp_default_devmode(snum) && !info->devmode) {
3892 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3893 printername));
3894 info->devmode = construct_nt_devicemode(printername);
3897 slprintf( adevice, sizeof(adevice), "%s", info->printername );
3898 if (info->devmode) {
3899 fstrcpy(info->devmode->devicename, adevice);
3902 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
3903 DEBUG(0,("unpack_values: talloc() failed!\n"));
3904 SAFE_FREE(dbuf.dptr);
3905 return WERR_NOMEM;
3907 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
3909 /* This will get the current RPC talloc context, but we should be
3910 passing this as a parameter... fixme... JRA ! */
3912 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
3913 SAFE_FREE(dbuf.dptr);
3914 return WERR_NOMEM;
3917 /* Fix for OS/2 drivers. */
3919 if (get_remote_arch() == RA_OS2) {
3920 map_to_os2_driver(info->drivername);
3923 SAFE_FREE(dbuf.dptr);
3925 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3926 sharename, info->printername, info->drivername));
3928 return WERR_OK;
3931 /****************************************************************************
3932 Debugging function, dump at level 6 the struct in the logs.
3933 ****************************************************************************/
3934 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3936 uint32 result;
3937 NT_PRINTER_INFO_LEVEL_2 *info2;
3939 DEBUG(106,("Dumping printer at level [%d]\n", level));
3941 switch (level) {
3942 case 2:
3944 if (printer->info_2 == NULL)
3945 result=5;
3946 else
3948 info2=printer->info_2;
3950 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3951 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3952 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3953 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3954 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3955 DEBUGADD(106,("status:[%d]\n", info2->status));
3956 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3957 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3958 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3959 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3960 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3962 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3963 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3964 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3965 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3966 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3967 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3968 DEBUGADD(106,("location:[%s]\n", info2->location));
3969 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3970 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3971 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3972 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3973 result=0;
3975 break;
3977 default:
3978 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3979 result=1;
3980 break;
3983 return result;
3986 /****************************************************************************
3987 Update the changeid time.
3988 This is SO NASTY as some drivers need this to change, others need it
3989 static. This value will change every second, and I must hope that this
3990 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3991 UTAH ! JRA.
3992 ****************************************************************************/
3994 static uint32 rev_changeid(void)
3996 struct timeval tv;
3998 get_process_uptime(&tv);
4000 #if 1 /* JERRY */
4001 /* Return changeid as msec since spooler restart */
4002 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4003 #else
4005 * This setting seems to work well but is too untested
4006 * to replace the above calculation. Left in for experiementation
4007 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4009 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4010 #endif
4015 * The function below are the high level ones.
4016 * only those ones must be called from the spoolss code.
4017 * JFM.
4020 /****************************************************************************
4021 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4022 ****************************************************************************/
4024 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4026 WERROR result;
4028 dump_a_printer(printer, level);
4030 switch (level) {
4031 case 2:
4034 * Update the changestamp. Emperical tests show that the
4035 * ChangeID is always updated,but c_setprinter is
4036 * global spooler variable (not per printer).
4039 /* ChangeID **must** be increasing over the lifetime
4040 of client's spoolss service in order for the
4041 client's cache to show updates */
4043 printer->info_2->changeid = rev_changeid();
4046 * Because one day someone will ask:
4047 * NT->NT An admin connection to a remote
4048 * printer show changes imeediately in
4049 * the properities dialog
4051 * A non-admin connection will only show the
4052 * changes after viewing the properites page
4053 * 2 times. Seems to be related to a
4054 * race condition in the client between the spooler
4055 * updating the local cache and the Explorer.exe GUI
4056 * actually displaying the properties.
4058 * This is fixed in Win2k. admin/non-admin
4059 * connections both display changes immediately.
4061 * 14/12/01 --jerry
4064 result=update_a_printer_2(printer->info_2);
4066 break;
4068 default:
4069 result=WERR_UNKNOWN_LEVEL;
4070 break;
4073 return result;
4076 /****************************************************************************
4077 Initialize printer devmode & data with previously saved driver init values.
4078 ****************************************************************************/
4080 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4082 int len = 0;
4083 pstring key;
4084 TDB_DATA dbuf;
4085 NT_PRINTER_INFO_LEVEL_2 info;
4088 ZERO_STRUCT(info);
4091 * Delete any printer data 'values' already set. When called for driver
4092 * replace, there will generally be some, but during an add printer, there
4093 * should not be any (if there are delete them).
4096 if ( info_ptr->data )
4097 delete_all_printer_data( info_ptr, "" );
4099 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
4101 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4102 if (!dbuf.dptr) {
4104 * When changing to a driver that has no init info in the tdb, remove
4105 * the previous drivers init info and leave the new on blank.
4107 free_nt_devicemode(&info_ptr->devmode);
4108 return False;
4112 * Get the saved DEVMODE..
4115 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4118 * The saved DEVMODE contains the devicename from the printer used during
4119 * the initialization save. Change it to reflect the new printer.
4122 if ( info.devmode ) {
4123 ZERO_STRUCT(info.devmode->devicename);
4124 fstrcpy(info.devmode->devicename, info_ptr->printername);
4128 * NT/2k does not change out the entire DeviceMode of a printer
4129 * when changing the driver. Only the driverextra, private, &
4130 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4132 * Later examination revealed that Windows NT/2k does reset the
4133 * the printer's device mode, bit **only** when you change a
4134 * property of the device mode such as the page orientation.
4135 * --jerry
4139 /* Bind the saved DEVMODE to the new the printer */
4141 free_nt_devicemode(&info_ptr->devmode);
4142 info_ptr->devmode = info.devmode;
4144 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4145 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4147 /* Add the printer data 'values' to the new printer */
4149 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4150 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4151 return False;
4154 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4157 SAFE_FREE(dbuf.dptr);
4159 return True;
4162 /****************************************************************************
4163 Initialize printer devmode & data with previously saved driver init values.
4164 When a printer is created using AddPrinter, the drivername bound to the
4165 printer is used to lookup previously saved driver initialization info, which
4166 is bound to the new printer.
4167 ****************************************************************************/
4169 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4171 BOOL result = False;
4173 switch (level) {
4174 case 2:
4175 result = set_driver_init_2(printer->info_2);
4176 break;
4178 default:
4179 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4180 level));
4181 break;
4184 return result;
4187 /****************************************************************************
4188 Delete driver init data stored for a specified driver
4189 ****************************************************************************/
4191 BOOL del_driver_init(char *drivername)
4193 pstring key;
4195 if (!drivername || !*drivername) {
4196 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4197 return False;
4200 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
4202 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
4204 return (tdb_delete_bystring(tdb_drivers, key) == 0);
4207 /****************************************************************************
4208 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4209 in the tdb. Note: this is different from the driver entry and the printer
4210 entry. There should be a single driver init entry for each driver regardless
4211 of whether it was installed from NT or 2K. Technically, they should be
4212 different, but they work out to the same struct.
4213 ****************************************************************************/
4215 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4217 pstring key;
4218 uint8 *buf;
4219 int buflen, len, ret;
4220 TDB_DATA dbuf;
4222 buf = NULL;
4223 buflen = 0;
4225 again:
4226 len = 0;
4227 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4229 len += pack_values( info->data, buf+len, buflen-len );
4231 if (buflen < len) {
4232 buf = (uint8 *)SMB_REALLOC(buf, len);
4233 if (!buf) {
4234 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4235 ret = -1;
4236 goto done;
4238 buflen = len;
4239 goto again;
4242 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
4244 dbuf.dptr = buf;
4245 dbuf.dsize = len;
4247 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4249 done:
4250 if (ret == -1)
4251 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4253 SAFE_FREE(buf);
4255 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4256 info->sharename, info->drivername));
4258 return ret;
4261 /****************************************************************************
4262 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4263 ****************************************************************************/
4265 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4267 uint32 result;
4269 dump_a_printer(printer, level);
4271 switch (level) {
4272 case 2:
4273 result = update_driver_init_2(printer->info_2);
4274 break;
4275 default:
4276 result = 1;
4277 break;
4280 return result;
4283 /****************************************************************************
4284 Convert the printer data value, a REG_BINARY array, into an initialization
4285 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4286 got to keep the endians happy :).
4287 ****************************************************************************/
4289 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
4291 BOOL result = False;
4292 prs_struct ps;
4293 DEVICEMODE devmode;
4295 ZERO_STRUCT(devmode);
4297 prs_init(&ps, 0, ctx, UNMARSHALL);
4298 ps.data_p = (char *)data;
4299 ps.buffer_size = data_len;
4301 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
4302 result = convert_devicemode("", &devmode, &nt_devmode);
4303 else
4304 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
4306 return result;
4309 /****************************************************************************
4310 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4312 1. Use the driver's config DLL to this UNC printername and:
4313 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4314 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4315 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4317 The last step triggers saving the "driver initialization" information for
4318 this printer into the tdb. Later, new printers that use this driver will
4319 have this initialization information bound to them. This simulates the
4320 driver initialization, as if it had run on the Samba server (as it would
4321 have done on NT).
4323 The Win32 client side code requirement sucks! But until we can run arbitrary
4324 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4326 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4327 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4328 about it and you will realize why. JRR 010720
4329 ****************************************************************************/
4331 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4333 WERROR status = WERR_OK;
4334 TALLOC_CTX *ctx = NULL;
4335 NT_DEVICEMODE *nt_devmode = NULL;
4336 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4339 * When the DEVMODE is already set on the printer, don't try to unpack it.
4341 DEBUG(8,("save_driver_init_2: Enter...\n"));
4343 if ( !printer->info_2->devmode && data_len ) {
4345 * Set devmode on printer info, so entire printer initialization can be
4346 * saved to tdb.
4349 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4350 return WERR_NOMEM;
4352 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4353 status = WERR_NOMEM;
4354 goto done;
4357 ZERO_STRUCTP(nt_devmode);
4360 * The DEVMODE is held in the 'data' component of the param in raw binary.
4361 * Convert it to to a devmode structure
4363 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4364 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4365 status = WERR_INVALID_PARAM;
4366 goto done;
4369 printer->info_2->devmode = nt_devmode;
4373 * Pack up and add (or update) the DEVMODE and any current printer data to
4374 * a 'driver init' element in the tdb
4378 if ( update_driver_init(printer, 2) != 0 ) {
4379 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4380 status = WERR_NOMEM;
4381 goto done;
4385 * If driver initialization info was successfully saved, set the current
4386 * printer to match it. This allows initialization of the current printer
4387 * as well as the driver.
4389 status = mod_a_printer(printer, 2);
4390 if (!W_ERROR_IS_OK(status)) {
4391 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4392 printer->info_2->printername));
4395 done:
4396 talloc_destroy(ctx);
4397 free_nt_devicemode( &nt_devmode );
4399 printer->info_2->devmode = tmp_devmode;
4401 return status;
4404 /****************************************************************************
4405 Update the driver init info (DEVMODE and specifics) for a printer
4406 ****************************************************************************/
4408 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4410 WERROR status = WERR_OK;
4412 switch (level) {
4413 case 2:
4414 status = save_driver_init_2( printer, data, data_len );
4415 break;
4416 default:
4417 status = WERR_UNKNOWN_LEVEL;
4418 break;
4421 return status;
4424 /****************************************************************************
4425 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4427 Previously the code had a memory allocation problem because it always
4428 used the TALLOC_CTX from the Printer_entry*. This context lasts
4429 as a long as the original handle is open. So if the client made a lot
4430 of getprinter[data]() calls, the memory usage would climb. Now we use
4431 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4432 still use the Printer_entry->ctx for maintaining the cache copy though
4433 since that object must live as long as the handle by definition.
4434 --jerry
4436 ****************************************************************************/
4438 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4439 const char *sharename)
4441 WERROR result;
4442 fstring servername;
4444 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4446 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4447 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4448 return WERR_NOMEM;
4451 switch (level) {
4452 case 2:
4453 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4454 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4455 TALLOC_FREE( *pp_printer );
4456 return WERR_NOMEM;
4459 if ( print_hnd )
4460 fstrcpy( servername, print_hnd->servername );
4461 else {
4462 fstrcpy( servername, "%L" );
4463 standard_sub_basic( "", "", servername,
4464 sizeof(servername)-1 );
4467 result = get_a_printer_2( (*pp_printer)->info_2, servername, sharename );
4470 /* we have a new printer now. Save it with this handle */
4472 if ( !W_ERROR_IS_OK(result) ) {
4473 TALLOC_FREE( *pp_printer );
4474 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4475 sharename, (unsigned int)level, dos_errstr(result)));
4476 return result;
4479 dump_a_printer( *pp_printer, level);
4481 break;
4483 default:
4484 TALLOC_FREE( *pp_printer );
4485 return WERR_UNKNOWN_LEVEL;
4488 return WERR_OK;
4491 /****************************************************************************
4492 Deletes a NT_PRINTER_INFO_LEVEL struct.
4493 ****************************************************************************/
4495 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4497 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4499 if ( !printer )
4500 return 0;
4502 switch (level) {
4503 case 2:
4504 if ( printer->info_2 )
4505 free_nt_printer_info_level_2(&printer->info_2);
4506 break;
4508 default:
4509 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4510 return 1;
4513 TALLOC_FREE(*pp_printer);
4515 return 0;
4518 /****************************************************************************
4519 ****************************************************************************/
4520 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4522 uint32 result;
4523 DEBUG(104,("adding a printer at level [%d]\n", level));
4524 dump_a_printer_driver(driver, level);
4526 switch (level) {
4527 case 3:
4528 result=add_a_printer_driver_3(driver.info_3);
4529 break;
4531 case 6:
4532 result=add_a_printer_driver_6(driver.info_6);
4533 break;
4535 default:
4536 result=1;
4537 break;
4540 return result;
4542 /****************************************************************************
4543 ****************************************************************************/
4545 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4546 fstring drivername, const char *architecture, uint32 version)
4548 WERROR result;
4550 switch (level) {
4551 case 3:
4552 /* Sometime we just want any version of the driver */
4554 if ( version == DRIVER_ANY_VERSION ) {
4555 /* look for Win2k first and then for NT4 */
4556 result = get_a_printer_driver_3(&driver->info_3, drivername,
4557 architecture, 3);
4559 if ( !W_ERROR_IS_OK(result) ) {
4560 result = get_a_printer_driver_3( &driver->info_3,
4561 drivername, architecture, 2 );
4563 } else {
4564 result = get_a_printer_driver_3(&driver->info_3, drivername,
4565 architecture, version);
4567 break;
4569 default:
4570 result=W_ERROR(1);
4571 break;
4574 if (W_ERROR_IS_OK(result))
4575 dump_a_printer_driver(*driver, level);
4577 return result;
4580 /****************************************************************************
4581 ****************************************************************************/
4582 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4584 uint32 result;
4586 switch (level) {
4587 case 3:
4589 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4590 if (driver.info_3 != NULL)
4592 info3=driver.info_3;
4593 SAFE_FREE(info3->dependentfiles);
4594 ZERO_STRUCTP(info3);
4595 SAFE_FREE(info3);
4596 result=0;
4597 } else {
4598 result=4;
4600 break;
4602 case 6:
4604 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4605 if (driver.info_6 != NULL) {
4606 info6=driver.info_6;
4607 SAFE_FREE(info6->dependentfiles);
4608 SAFE_FREE(info6->previousnames);
4609 ZERO_STRUCTP(info6);
4610 SAFE_FREE(info6);
4611 result=0;
4612 } else {
4613 result=4;
4615 break;
4617 default:
4618 result=1;
4619 break;
4621 return result;
4625 /****************************************************************************
4626 Determine whether or not a particular driver is currently assigned
4627 to a printer
4628 ****************************************************************************/
4630 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4632 int snum;
4633 int n_services = lp_numservices();
4634 NT_PRINTER_INFO_LEVEL *printer = NULL;
4635 BOOL in_use = False;
4637 if ( !info_3 )
4638 return False;
4640 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4642 /* loop through the printers.tdb and check for the drivername */
4644 for (snum=0; snum<n_services && !in_use; snum++) {
4645 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4646 continue;
4648 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4649 continue;
4651 if ( strequal(info_3->name, printer->info_2->drivername) )
4652 in_use = True;
4654 free_a_printer( &printer, 2 );
4657 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4659 if ( in_use ) {
4660 NT_PRINTER_DRIVER_INFO_LEVEL d;
4661 WERROR werr;
4663 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
4665 /* we can still remove the driver if there is one of
4666 "Windows NT x86" version 2 or 3 left */
4668 if ( !strequal( "Windows NT x86", info_3->environment ) ) {
4669 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
4671 else {
4672 switch ( info_3->cversion ) {
4673 case 2:
4674 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
4675 break;
4676 case 3:
4677 werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
4678 break;
4679 default:
4680 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
4681 info_3->cversion));
4682 werr = WERR_UNKNOWN_PRINTER_DRIVER;
4683 break;
4687 /* now check the error code */
4689 if ( W_ERROR_IS_OK(werr) ) {
4690 /* it's ok to remove the driver, we have other architctures left */
4691 in_use = False;
4692 free_a_printer_driver( d, 3 );
4696 /* report that the driver is not in use by default */
4698 return in_use;
4702 /**********************************************************************
4703 Check to see if a ogiven file is in use by *info
4704 *********************************************************************/
4706 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4708 int i = 0;
4710 if ( !info )
4711 return False;
4713 if ( strequal(file, info->driverpath) )
4714 return True;
4716 if ( strequal(file, info->datafile) )
4717 return True;
4719 if ( strequal(file, info->configfile) )
4720 return True;
4722 if ( strequal(file, info->helpfile) )
4723 return True;
4725 /* see of there are any dependent files to examine */
4727 if ( !info->dependentfiles )
4728 return False;
4730 while ( *info->dependentfiles[i] ) {
4731 if ( strequal(file, info->dependentfiles[i]) )
4732 return True;
4733 i++;
4736 return False;
4740 /**********************************************************************
4741 Utility function to remove the dependent file pointed to by the
4742 input parameter from the list
4743 *********************************************************************/
4745 static void trim_dependent_file( fstring files[], int idx )
4748 /* bump everything down a slot */
4750 while( *files[idx+1] ) {
4751 fstrcpy( files[idx], files[idx+1] );
4752 idx++;
4755 *files[idx] = '\0';
4757 return;
4760 /**********************************************************************
4761 Check if any of the files used by src are also used by drv
4762 *********************************************************************/
4764 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4765 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4767 BOOL in_use = False;
4768 int i = 0;
4770 if ( !src || !drv )
4771 return False;
4773 /* check each file. Remove it from the src structure if it overlaps */
4775 if ( drv_file_in_use(src->driverpath, drv) ) {
4776 in_use = True;
4777 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4778 fstrcpy( src->driverpath, "" );
4781 if ( drv_file_in_use(src->datafile, drv) ) {
4782 in_use = True;
4783 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4784 fstrcpy( src->datafile, "" );
4787 if ( drv_file_in_use(src->configfile, drv) ) {
4788 in_use = True;
4789 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4790 fstrcpy( src->configfile, "" );
4793 if ( drv_file_in_use(src->helpfile, drv) ) {
4794 in_use = True;
4795 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4796 fstrcpy( src->helpfile, "" );
4799 /* are there any dependentfiles to examine? */
4801 if ( !src->dependentfiles )
4802 return in_use;
4804 while ( *src->dependentfiles[i] ) {
4805 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4806 in_use = True;
4807 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4808 trim_dependent_file( src->dependentfiles, i );
4809 } else
4810 i++;
4813 return in_use;
4816 /****************************************************************************
4817 Determine whether or not a particular driver files are currently being
4818 used by any other driver.
4820 Return value is True if any files were in use by other drivers
4821 and False otherwise.
4823 Upon return, *info has been modified to only contain the driver files
4824 which are not in use
4825 ****************************************************************************/
4827 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4829 int i;
4830 int ndrivers;
4831 uint32 version;
4832 fstring *list = NULL;
4833 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4835 if ( !info )
4836 return False;
4838 version = info->cversion;
4840 /* loop over all driver versions */
4842 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4844 /* get the list of drivers */
4846 list = NULL;
4847 ndrivers = get_ntdrivers(&list, info->environment, version);
4849 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4850 ndrivers, info->environment, version));
4852 /* check each driver for overlap in files */
4854 for (i=0; i<ndrivers; i++) {
4855 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4857 ZERO_STRUCT(driver);
4859 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4860 SAFE_FREE(list);
4861 return True;
4864 /* check if d2 uses any files from d1 */
4865 /* only if this is a different driver than the one being deleted */
4867 if ( !strequal(info->name, driver.info_3->name) ) {
4868 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4869 free_a_printer_driver(driver, 3);
4870 SAFE_FREE( list );
4871 return True;
4875 free_a_printer_driver(driver, 3);
4878 SAFE_FREE(list);
4880 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4882 driver.info_3 = info;
4884 if ( DEBUGLEVEL >= 20 )
4885 dump_a_printer_driver( driver, 3 );
4887 return False;
4890 /****************************************************************************
4891 Actually delete the driver files. Make sure that
4892 printer_driver_files_in_use() return False before calling
4893 this.
4894 ****************************************************************************/
4896 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4898 int i = 0;
4899 char *s;
4900 pstring file;
4901 connection_struct *conn;
4902 DATA_BLOB null_pw;
4903 NTSTATUS nt_status;
4904 fstring res_type;
4905 SMB_STRUCT_STAT st;
4907 if ( !info_3 )
4908 return False;
4910 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4913 * Connect to the print$ share under the same account as the
4914 * user connected to the rpc pipe. Note we must be root to
4915 * do this.
4918 null_pw = data_blob_null;
4919 fstrcpy(res_type, "A:");
4920 become_root();
4921 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4922 unbecome_root();
4924 if ( !conn ) {
4925 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4926 return False;
4929 if ( !CAN_WRITE(conn) ) {
4930 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
4931 return False;
4934 /* Save who we are - we are temporarily becoming the connection user. */
4936 if ( !become_user(conn, conn->vuid) ) {
4937 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4938 return False;
4941 /* now delete the files; must strip the '\print$' string from
4942 fron of path */
4944 if ( *info_3->driverpath ) {
4945 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4946 pstrcpy( file, s );
4947 driver_unix_convert(conn,file,&st);
4948 DEBUG(10,("deleting driverfile [%s]\n", s));
4949 unlink_internals(conn, NULL, 0, file, False);
4953 if ( *info_3->configfile ) {
4954 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4955 pstrcpy( file, s );
4956 driver_unix_convert(conn,file,&st);
4957 DEBUG(10,("deleting configfile [%s]\n", s));
4958 unlink_internals(conn, NULL, 0, file, False);
4962 if ( *info_3->datafile ) {
4963 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4964 pstrcpy( file, s );
4965 driver_unix_convert(conn,file,&st);
4966 DEBUG(10,("deleting datafile [%s]\n", s));
4967 unlink_internals(conn, NULL, 0, file, False);
4971 if ( *info_3->helpfile ) {
4972 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4973 pstrcpy( file, s );
4974 driver_unix_convert(conn,file,&st);
4975 DEBUG(10,("deleting helpfile [%s]\n", s));
4976 unlink_internals(conn, NULL, 0, file, False);
4980 /* check if we are done removing files */
4982 if ( info_3->dependentfiles ) {
4983 while ( info_3->dependentfiles[i][0] ) {
4984 char *p;
4986 /* bypass the "\print$" portion of the path */
4988 if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4989 pstrcpy( file, p );
4990 driver_unix_convert(conn,file,&st);
4991 DEBUG(10,("deleting dependent file [%s]\n", file));
4992 unlink_internals(conn, NULL, 0, file, False);
4995 i++;
4999 unbecome_user();
5001 return True;
5004 /****************************************************************************
5005 Remove a printer driver from the TDB. This assumes that the the driver was
5006 previously looked up.
5007 ***************************************************************************/
5009 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
5010 uint32 version, BOOL delete_files )
5012 pstring key;
5013 const char *arch;
5014 TDB_DATA dbuf;
5015 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
5017 /* delete the tdb data first */
5019 arch = get_short_archi(info_3->environment);
5020 if (!arch) {
5021 return WERR_UNKNOWN_PRINTER_DRIVER;
5023 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
5024 arch, version, info_3->name);
5026 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5027 key, delete_files ? "TRUE" : "FALSE" ));
5029 ctr.info_3 = info_3;
5030 dump_a_printer_driver( ctr, 3 );
5032 /* check if the driver actually exists for this environment */
5034 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5035 if ( !dbuf.dptr ) {
5036 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5037 return WERR_UNKNOWN_PRINTER_DRIVER;
5040 SAFE_FREE( dbuf.dptr );
5042 /* ok... the driver exists so the delete should return success */
5044 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5045 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5046 return WERR_ACCESS_DENIED;
5050 * now delete any associated files if delete_files == True
5051 * even if this part failes, we return succes because the
5052 * driver doesn not exist any more
5055 if ( delete_files )
5056 delete_driver_files( info_3, user );
5059 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5061 return WERR_OK;
5064 /****************************************************************************
5065 Store a security desc for a printer.
5066 ****************************************************************************/
5068 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5070 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5071 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5072 prs_struct ps;
5073 TALLOC_CTX *mem_ctx = NULL;
5074 TDB_DATA kbuf;
5075 WERROR status;
5077 mem_ctx = talloc_init("nt_printing_setsec");
5078 if (mem_ctx == NULL)
5079 return WERR_NOMEM;
5081 /* The old owner and group sids of the security descriptor are not
5082 present when new ACEs are added or removed by changing printer
5083 permissions through NT. If they are NULL in the new security
5084 descriptor then copy them over from the old one. */
5086 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5087 DOM_SID *owner_sid, *group_sid;
5088 SEC_ACL *dacl, *sacl;
5089 SEC_DESC *psd = NULL;
5090 size_t size;
5092 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5093 status = WERR_NOMEM;
5094 goto out;
5097 /* Pick out correct owner and group sids */
5099 owner_sid = secdesc_ctr->sd->owner_sid ?
5100 secdesc_ctr->sd->owner_sid :
5101 old_secdesc_ctr->sd->owner_sid;
5103 group_sid = secdesc_ctr->sd->group_sid ?
5104 secdesc_ctr->sd->group_sid :
5105 old_secdesc_ctr->sd->group_sid;
5107 dacl = secdesc_ctr->sd->dacl ?
5108 secdesc_ctr->sd->dacl :
5109 old_secdesc_ctr->sd->dacl;
5111 sacl = secdesc_ctr->sd->sacl ?
5112 secdesc_ctr->sd->sacl :
5113 old_secdesc_ctr->sd->sacl;
5115 /* Make a deep copy of the security descriptor */
5117 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5118 owner_sid, group_sid,
5119 sacl,
5120 dacl,
5121 &size);
5123 if (!psd) {
5124 status = WERR_NOMEM;
5125 goto out;
5128 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5131 if (!new_secdesc_ctr) {
5132 new_secdesc_ctr = secdesc_ctr;
5135 /* Store the security descriptor in a tdb */
5137 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sd) +
5138 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
5140 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
5141 &ps, 1)) {
5142 status = WERR_BADFUNC;
5143 goto out;
5146 kbuf = make_printers_secdesc_tdbkey( sharename );
5148 if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
5149 status = WERR_OK;
5150 } else {
5151 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5152 status = WERR_BADFUNC;
5155 /* Free malloc'ed memory */
5157 out:
5159 prs_mem_free(&ps);
5160 if (mem_ctx)
5161 talloc_destroy(mem_ctx);
5162 return status;
5165 /****************************************************************************
5166 Construct a default security descriptor buffer for a printer.
5167 ****************************************************************************/
5169 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5171 SEC_ACE ace[5]; /* max number of ace entries */
5172 int i = 0;
5173 SEC_ACCESS sa;
5174 SEC_ACL *psa = NULL;
5175 SEC_DESC_BUF *sdb = NULL;
5176 SEC_DESC *psd = NULL;
5177 DOM_SID adm_sid;
5178 size_t sd_size;
5180 /* Create an ACE where Everyone is allowed to print */
5182 init_sec_access(&sa, PRINTER_ACE_PRINT);
5183 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5184 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5186 /* Add the domain admins group if we are a DC */
5188 if ( IS_DC ) {
5189 DOM_SID domadmins_sid;
5191 sid_copy(&domadmins_sid, get_global_sam_sid());
5192 sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
5194 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5195 init_sec_ace(&ace[i++], &domadmins_sid,
5196 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5197 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5198 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5199 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5201 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5202 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5204 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5205 init_sec_ace(&ace[i++], &adm_sid,
5206 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5207 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5208 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5209 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5212 /* add BUILTIN\Administrators as FULL CONTROL */
5214 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
5215 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5216 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5217 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5218 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5219 SEC_ACE_TYPE_ACCESS_ALLOWED,
5220 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5222 /* Make the security descriptor owned by the BUILTIN\Administrators */
5224 /* The ACL revision number in rpc_secdesc.h differs from the one
5225 created by NT when setting ACE entries in printer
5226 descriptors. NT4 complains about the property being edited by a
5227 NT5 machine. */
5229 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5230 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5231 &global_sid_Builtin_Administrators,
5232 &global_sid_Builtin_Administrators,
5233 NULL, psa, &sd_size);
5236 if (!psd) {
5237 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5238 return NULL;
5241 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5243 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5244 (unsigned int)sd_size));
5246 return sdb;
5249 /****************************************************************************
5250 Get a security desc for a printer.
5251 ****************************************************************************/
5253 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5255 prs_struct ps;
5256 TDB_DATA kbuf;
5257 char *temp;
5259 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5260 sharename = temp + 1;
5263 ZERO_STRUCT(ps);
5265 /* Fetch security descriptor from tdb */
5267 kbuf = make_printers_secdesc_tdbkey( sharename );
5269 if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
5270 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5272 prs_mem_free(&ps);
5274 DEBUG(4,("using default secdesc for %s\n", sharename));
5276 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
5277 return False;
5280 /* Save default security descriptor for later */
5282 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sd) +
5283 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
5285 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
5286 tdb_prs_store(tdb_printers, kbuf, &ps);
5289 prs_mem_free(&ps);
5291 return True;
5294 prs_mem_free(&ps);
5296 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5297 this security descriptor has been created when winbindd was
5298 down. Take ownership of security descriptor. */
5300 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5301 DOM_SID owner_sid;
5303 /* Change sd owner to workgroup administrator */
5305 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5306 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5307 SEC_DESC *psd = NULL;
5308 size_t size;
5310 /* Create new sd */
5312 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5314 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5315 &owner_sid,
5316 (*secdesc_ctr)->sd->group_sid,
5317 (*secdesc_ctr)->sd->sacl,
5318 (*secdesc_ctr)->sd->dacl,
5319 &size);
5321 if (!psd) {
5322 return False;
5325 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5326 if (!new_secdesc_ctr) {
5327 return False;
5330 /* Swap with other one */
5332 *secdesc_ctr = new_secdesc_ctr;
5334 /* Set it */
5336 nt_printing_setsec(sharename, *secdesc_ctr);
5340 if (DEBUGLEVEL >= 10) {
5341 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5342 int i;
5344 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5345 sharename, the_acl->num_aces));
5347 for (i = 0; i < the_acl->num_aces; i++) {
5348 fstring sid_str;
5350 sid_to_string(sid_str, &the_acl->aces[i].trustee);
5352 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
5353 the_acl->aces[i].type, the_acl->aces[i].flags,
5354 the_acl->aces[i].access_mask));
5358 return True;
5361 /* error code:
5362 0: everything OK
5363 1: level not implemented
5364 2: file doesn't exist
5365 3: can't allocate memory
5366 4: can't free memory
5367 5: non existant struct
5371 A printer and a printer driver are 2 different things.
5372 NT manages them separatelly, Samba does the same.
5373 Why ? Simply because it's easier and it makes sense !
5375 Now explanation: You have 3 printers behind your samba server,
5376 2 of them are the same make and model (laser A and B). But laser B
5377 has an 3000 sheet feeder and laser A doesn't such an option.
5378 Your third printer is an old dot-matrix model for the accounting :-).
5380 If the /usr/local/samba/lib directory (default dir), you will have
5381 5 files to describe all of this.
5383 3 files for the printers (1 by printer):
5384 NTprinter_laser A
5385 NTprinter_laser B
5386 NTprinter_accounting
5387 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5388 NTdriver_printer model X
5389 NTdriver_printer model Y
5391 jfm: I should use this comment for the text file to explain
5392 same thing for the forms BTW.
5393 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5397 /* Convert generic access rights to printer object specific access rights.
5398 It turns out that NT4 security descriptors use generic access rights and
5399 NT5 the object specific ones. */
5401 void map_printer_permissions(SEC_DESC *sd)
5403 int i;
5405 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5406 se_map_generic(&sd->dacl->aces[i].access_mask,
5407 &printer_generic_mapping);
5411 /****************************************************************************
5412 Check a user has permissions to perform the given operation. We use the
5413 permission constants defined in include/rpc_spoolss.h to check the various
5414 actions we perform when checking printer access.
5416 PRINTER_ACCESS_ADMINISTER:
5417 print_queue_pause, print_queue_resume, update_printer_sec,
5418 update_printer, spoolss_addprinterex_level_2,
5419 _spoolss_setprinterdata
5421 PRINTER_ACCESS_USE:
5422 print_job_start
5424 JOB_ACCESS_ADMINISTER:
5425 print_job_delete, print_job_pause, print_job_resume,
5426 print_queue_purge
5428 Try access control in the following order (for performance reasons):
5429 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
5430 2) check security descriptor (bit comparisons in memory)
5431 3) "printer admins" (may result in numerous calls to winbind)
5433 ****************************************************************************/
5434 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5436 SEC_DESC_BUF *secdesc = NULL;
5437 uint32 access_granted;
5438 NTSTATUS status;
5439 BOOL result;
5440 const char *pname;
5441 TALLOC_CTX *mem_ctx = NULL;
5442 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5444 /* If user is NULL then use the current_user structure */
5446 if (!user)
5447 user = &current_user;
5449 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5451 if ( user->ut.uid == 0 || user_has_privileges(user->nt_user_token, &se_printop ) ) {
5452 return True;
5455 /* Get printer name */
5457 pname = PRINTERNAME(snum);
5459 if (!pname || !*pname) {
5460 errno = EACCES;
5461 return False;
5464 /* Get printer security descriptor */
5466 if(!(mem_ctx = talloc_init("print_access_check"))) {
5467 errno = ENOMEM;
5468 return False;
5471 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5472 talloc_destroy(mem_ctx);
5473 errno = ENOMEM;
5474 return False;
5477 if (access_type == JOB_ACCESS_ADMINISTER) {
5478 SEC_DESC_BUF *parent_secdesc = secdesc;
5480 /* Create a child security descriptor to check permissions
5481 against. This is because print jobs are child objects
5482 objects of a printer. */
5484 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sd, False);
5486 if (!secdesc) {
5487 talloc_destroy(mem_ctx);
5488 errno = ENOMEM;
5489 return False;
5492 /* Now this is the bit that really confuses me. The access
5493 type needs to be changed from JOB_ACCESS_ADMINISTER to
5494 PRINTER_ACCESS_ADMINISTER for this to work. Something
5495 to do with the child (job) object becoming like a
5496 printer?? -tpot */
5498 access_type = PRINTER_ACCESS_ADMINISTER;
5501 /* Check access */
5503 map_printer_permissions(secdesc->sd);
5505 result = se_access_check(secdesc->sd, user->nt_user_token, access_type,
5506 &access_granted, &status);
5508 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5510 /* see if we need to try the printer admin list */
5512 if ((access_granted == 0) &&
5513 (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
5514 user->nt_user_token,
5515 lp_printer_admin(snum)))) {
5516 talloc_destroy(mem_ctx);
5517 return True;
5520 talloc_destroy(mem_ctx);
5522 if (!result) {
5523 errno = EACCES;
5526 return result;
5529 /****************************************************************************
5530 Check the time parameters allow a print operation.
5531 *****************************************************************************/
5533 BOOL print_time_access_check(const char *servicename)
5535 NT_PRINTER_INFO_LEVEL *printer = NULL;
5536 BOOL ok = False;
5537 time_t now = time(NULL);
5538 struct tm *t;
5539 uint32 mins;
5541 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5542 return False;
5544 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5545 ok = True;
5547 t = gmtime(&now);
5548 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5550 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5551 ok = True;
5553 free_a_printer(&printer, 2);
5555 if (!ok)
5556 errno = EACCES;
5558 return ok;
5561 /****************************************************************************
5562 Fill in the servername sent in the _spoolss_open_printer_ex() call
5563 ****************************************************************************/
5565 char* get_server_name( Printer_entry *printer )
5567 return printer->servername;