Make pcap headers private
[Samba.git] / source3 / printing / nt_printing.c
bloba8bc577370544e8ba42f9cb8bc381026f3893736
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"
23 #include "librpc/gen_ndr/messaging.h"
24 #include "printing/pcap.h"
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
40 #define NTDRIVERS_DATABASE_VERSION_4 4 /* fix generic bits in security descriptors */
41 #define NTDRIVERS_DATABASE_VERSION_5 5 /* normalize keys in ntprinters.tdb */
43 /* Map generic permissions to printer object specific permissions */
45 const struct generic_mapping printer_generic_mapping = {
46 PRINTER_READ,
47 PRINTER_WRITE,
48 PRINTER_EXECUTE,
49 PRINTER_ALL_ACCESS
52 const struct 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 const struct generic_mapping printserver_generic_mapping = {
62 SERVER_READ,
63 SERVER_WRITE,
64 SERVER_EXECUTE,
65 SERVER_ALL_ACCESS
68 const struct generic_mapping printserver_std_mapping = {
69 SERVER_READ,
70 SERVER_WRITE,
71 SERVER_EXECUTE,
72 SERVER_ALL_ACCESS
75 /* Map generic permissions to job object specific permissions */
77 const struct generic_mapping job_generic_mapping = {
78 JOB_READ,
79 JOB_WRITE,
80 JOB_EXECUTE,
81 JOB_ALL_ACCESS
84 /* We need one default form to support our default printer. Msoft adds the
85 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
86 array index). Letter is always first, so (for the current code) additions
87 always put things in the correct order. */
88 static const nt_forms_struct default_forms[] = {
89 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
90 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
91 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
92 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
93 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
94 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
95 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
96 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
97 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
98 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
99 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
100 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
101 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
102 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
103 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
104 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
105 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
106 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
107 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
108 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
109 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
110 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
111 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
112 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
113 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
114 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
115 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
116 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
117 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
118 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
119 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
120 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
121 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
123 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
124 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
125 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
126 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
127 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
128 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
129 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
130 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
131 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
132 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
133 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
134 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
135 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
136 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
137 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
138 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
139 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
140 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
141 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
142 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
143 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
144 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
145 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
146 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
147 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
148 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
149 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
150 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
151 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
152 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
153 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
154 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
155 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
156 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
157 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
158 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
159 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
160 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
161 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
162 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
163 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
164 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
165 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
166 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
167 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
168 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
169 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
170 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
171 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
172 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
173 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
174 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
175 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
176 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
177 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
178 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
179 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
180 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
181 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
182 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
183 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
184 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
185 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
186 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
187 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
188 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
189 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
190 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
191 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
192 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
193 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
194 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
195 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
196 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
197 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
198 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
199 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
200 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
201 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
202 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
203 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
204 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
205 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
206 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
209 static const struct print_architecture_table_node archi_table[]= {
211 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
212 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
213 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
214 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
215 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
216 {"Windows IA64", SPL_ARCH_IA64, 3 },
217 {"Windows x64", SPL_ARCH_X64, 3 },
218 {NULL, "", -1 }
222 /****************************************************************************
223 generate a new TDB_DATA key for storing a printer
224 ****************************************************************************/
226 static TDB_DATA make_printer_tdbkey(TALLOC_CTX *ctx, const char *sharename )
228 fstring share;
229 char *keystr = NULL;
230 TDB_DATA key;
232 fstrcpy(share, sharename);
233 strlower_m(share);
235 keystr = talloc_asprintf(ctx, "%s%s", PRINTERS_PREFIX, share);
236 key = string_term_tdb_data(keystr ? keystr : "");
238 return key;
241 /****************************************************************************
242 generate a new TDB_DATA key for storing a printer security descriptor
243 ****************************************************************************/
245 static TDB_DATA make_printers_secdesc_tdbkey(TALLOC_CTX *ctx,
246 const char* sharename )
248 fstring share;
249 char *keystr = NULL;
250 TDB_DATA key;
252 fstrcpy(share, sharename );
253 strlower_m(share);
255 keystr = talloc_asprintf(ctx, "%s%s", SECDESC_PREFIX, share);
256 key = string_term_tdb_data(keystr ? keystr : "");
258 return key;
261 /****************************************************************************
262 ****************************************************************************/
264 static bool upgrade_to_version_3(void)
266 TDB_DATA kbuf, newkey, dbuf;
268 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
270 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
271 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
273 dbuf = tdb_fetch(tdb_drivers, kbuf);
275 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
276 DEBUG(0,("upgrade_to_version_3:moving form\n"));
277 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
278 SAFE_FREE(dbuf.dptr);
279 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
280 return False;
282 if (tdb_delete(tdb_drivers, kbuf) != 0) {
283 SAFE_FREE(dbuf.dptr);
284 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
285 return False;
289 if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
290 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
291 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
292 SAFE_FREE(dbuf.dptr);
293 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
294 return False;
296 if (tdb_delete(tdb_drivers, kbuf) != 0) {
297 SAFE_FREE(dbuf.dptr);
298 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
299 return False;
303 if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
304 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
305 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
306 SAFE_FREE(dbuf.dptr);
307 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
308 return False;
310 if (tdb_delete(tdb_drivers, kbuf) != 0) {
311 SAFE_FREE(dbuf.dptr);
312 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
313 return False;
317 SAFE_FREE(dbuf.dptr);
320 return True;
323 /*******************************************************************
324 Fix an issue with security descriptors. Printer sec_desc must
325 use more than the generic bits that were previously used
326 in <= 3.0.14a. They must also have a owner and group SID assigned.
327 Otherwise, any printers than have been migrated to a Windows
328 host using printmig.exe will not be accessible.
329 *******************************************************************/
331 static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
332 TDB_DATA data, void *state )
334 NTSTATUS status;
335 SEC_DESC_BUF *sd_orig = NULL;
336 SEC_DESC_BUF *sd_new, *sd_store;
337 SEC_DESC *sec, *new_sec;
338 TALLOC_CTX *ctx = state;
339 int result, i;
340 uint32 sd_size;
341 size_t size_new_sec;
343 if (!data.dptr || data.dsize == 0) {
344 return 0;
347 if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) != 0 ) {
348 return 0;
351 /* upgrade the security descriptor */
353 status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
354 if (!NT_STATUS_IS_OK(status)) {
355 /* delete bad entries */
356 DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
357 (const char *)key.dptr ));
358 tdb_delete( tdb_printers, key );
359 return 0;
362 if (!sd_orig) {
363 return 0;
365 sec = sd_orig->sd;
367 /* is this even valid? */
369 if ( !sec->dacl ) {
370 return 0;
373 /* update access masks */
375 for ( i=0; i<sec->dacl->num_aces; i++ ) {
376 switch ( sec->dacl->aces[i].access_mask ) {
377 case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
378 sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
379 break;
381 case GENERIC_ALL_ACCESS:
382 sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
383 break;
385 case READ_CONTROL_ACCESS:
386 sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
388 default: /* no change */
389 break;
393 /* create a new SEC_DESC with the appropriate owner and group SIDs */
395 new_sec = make_sec_desc( ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
396 &global_sid_Builtin_Administrators,
397 &global_sid_Builtin_Administrators,
398 NULL, NULL, &size_new_sec );
399 if (!new_sec) {
400 return 0;
402 sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
403 if (!sd_new) {
404 return 0;
407 if ( !(sd_store = sec_desc_merge_buf( ctx, sd_new, sd_orig )) ) {
408 DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
409 return 0;
412 /* store it back */
414 sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
415 + sizeof(SEC_DESC_BUF);
417 status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
418 if (!NT_STATUS_IS_OK(status)) {
419 DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
420 return 0;
423 result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
425 /* 0 to continue and non-zero to stop traversal */
427 return (result == -1);
430 /*******************************************************************
431 *******************************************************************/
433 static bool upgrade_to_version_4(void)
435 TALLOC_CTX *ctx;
436 int result;
438 DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
440 if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
441 return False;
443 result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
445 talloc_destroy( ctx );
447 return ( result != -1 );
450 /*******************************************************************
451 Fix an issue with security descriptors. Printer sec_desc must
452 use more than the generic bits that were previously used
453 in <= 3.0.14a. They must also have a owner and group SID assigned.
454 Otherwise, any printers than have been migrated to a Windows
455 host using printmig.exe will not be accessible.
456 *******************************************************************/
458 static int normalize_printers_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
459 TDB_DATA data, void *state )
461 TALLOC_CTX *ctx = talloc_tos();
462 TDB_DATA new_key;
464 if (!data.dptr || data.dsize == 0)
465 return 0;
467 /* upgrade printer records and security descriptors */
469 if ( strncmp((const char *) key.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX) ) == 0 ) {
470 new_key = make_printer_tdbkey(ctx, (const char *)key.dptr+strlen(PRINTERS_PREFIX) );
472 else if ( strncmp((const char *) key.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX) ) == 0 ) {
473 new_key = make_printers_secdesc_tdbkey(ctx, (const char *)key.dptr+strlen(SECDESC_PREFIX) );
475 else {
476 /* ignore this record */
477 return 0;
480 /* delete the original record and store under the normalized key */
482 if ( tdb_delete( the_tdb, key ) != 0 ) {
483 DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
484 key.dptr));
485 return 1;
488 if ( tdb_store( the_tdb, new_key, data, TDB_REPLACE) != 0 ) {
489 DEBUG(0,("normalize_printers_fn: failed to store new record for [%s]!\n",
490 key.dptr));
491 return 1;
494 return 0;
497 /*******************************************************************
498 *******************************************************************/
500 static bool upgrade_to_version_5(void)
502 TALLOC_CTX *ctx;
503 int result;
505 DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
507 if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
508 return False;
510 result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
512 talloc_destroy( ctx );
514 return ( result != -1 );
517 /****************************************************************************
518 Open the NT printing tdbs. Done once before fork().
519 ****************************************************************************/
521 bool nt_printing_init(struct messaging_context *msg_ctx)
523 const char *vstring = "INFO/version";
524 WERROR win_rc;
525 int32 vers_id;
527 if ( tdb_drivers && tdb_printers && tdb_forms )
528 return True;
530 if (tdb_drivers)
531 tdb_close(tdb_drivers);
532 tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
533 if (!tdb_drivers) {
534 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
535 state_path("ntdrivers.tdb"), strerror(errno) ));
536 return False;
539 if (tdb_printers)
540 tdb_close(tdb_printers);
541 tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
542 if (!tdb_printers) {
543 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
544 state_path("ntprinters.tdb"), strerror(errno) ));
545 return False;
548 if (tdb_forms)
549 tdb_close(tdb_forms);
550 tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
551 if (!tdb_forms) {
552 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
553 state_path("ntforms.tdb"), strerror(errno) ));
554 return False;
557 /* handle a Samba upgrade */
559 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
560 if (vers_id == -1) {
561 DEBUG(10, ("Fresh database\n"));
562 tdb_store_int32( tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5 );
563 vers_id = NTDRIVERS_DATABASE_VERSION_5;
566 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
568 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
569 if (!upgrade_to_version_3())
570 return False;
571 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
572 vers_id = NTDRIVERS_DATABASE_VERSION_3;
575 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
576 /* Written on a bigendian machine with old fetch_int code. Save as le. */
577 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
578 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
579 vers_id = NTDRIVERS_DATABASE_VERSION_3;
582 if (vers_id == NTDRIVERS_DATABASE_VERSION_3 ) {
583 if ( !upgrade_to_version_4() )
584 return False;
585 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_4);
586 vers_id = NTDRIVERS_DATABASE_VERSION_4;
589 if (vers_id == NTDRIVERS_DATABASE_VERSION_4 ) {
590 if ( !upgrade_to_version_5() )
591 return False;
592 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_5);
593 vers_id = NTDRIVERS_DATABASE_VERSION_5;
597 if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
598 DEBUG(0,("nt_printing_init: Unknown printer database version [%d]\n", vers_id));
599 return False;
603 update_c_setprinter(True);
606 * register callback to handle updating printers as new
607 * drivers are installed
610 messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
611 do_drv_upgrade_printer);
614 * register callback to handle updating printer data
615 * when a driver is initialized
618 messaging_register(msg_ctx, NULL, MSG_PRINTERDATA_INIT_RESET,
619 reset_all_printerdata);
621 /* of course, none of the message callbacks matter if you don't
622 tell messages.c that you interested in receiving PRINT_GENERAL
623 msgs. This is done in serverid_register() */
626 if ( lp_security() == SEC_ADS ) {
627 win_rc = check_published_printers();
628 if (!W_ERROR_IS_OK(win_rc))
629 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", win_errstr(win_rc)));
632 return True;
635 /*******************************************************************
636 Function to allow filename parsing "the old way".
637 ********************************************************************/
639 static NTSTATUS driver_unix_convert(connection_struct *conn,
640 const char *old_name,
641 struct smb_filename **smb_fname)
643 NTSTATUS status;
644 TALLOC_CTX *ctx = talloc_tos();
645 char *name = talloc_strdup(ctx, old_name);
647 if (!name) {
648 return NT_STATUS_NO_MEMORY;
650 unix_format(name);
651 name = unix_clean_name(ctx, name);
652 if (!name) {
653 return NT_STATUS_NO_MEMORY;
655 trim_string(name,"/","/");
657 status = unix_convert(ctx, conn, name, smb_fname, 0);
658 if (!NT_STATUS_IS_OK(status)) {
659 return NT_STATUS_NO_MEMORY;
662 return NT_STATUS_OK;
665 /*******************************************************************
666 tdb traversal function for counting printers.
667 ********************************************************************/
669 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
670 TDB_DATA data, void *context)
672 int *printer_count = (int*)context;
674 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
675 (*printer_count)++;
676 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
679 return 0;
682 /*******************************************************************
683 Update the spooler global c_setprinter. This variable is initialized
684 when the parent smbd starts with the number of existing printers. It
685 is monotonically increased by the current number of printers *after*
686 each add or delete printer RPC. Only Microsoft knows why... JRR020119
687 ********************************************************************/
689 uint32 update_c_setprinter(bool initialize)
691 int32 c_setprinter;
692 int32 printer_count = 0;
694 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
696 /* Traverse the tdb, counting the printers */
697 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
699 /* If initializing, set c_setprinter to current printers count
700 * otherwise, bump it by the current printer count
702 if (!initialize)
703 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
704 else
705 c_setprinter = printer_count;
707 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
708 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
710 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
712 return (uint32)c_setprinter;
715 /*******************************************************************
716 Get the spooler global c_setprinter, accounting for initialization.
717 ********************************************************************/
719 uint32 get_c_setprinter(void)
721 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
723 if (c_setprinter == (int32)-1)
724 c_setprinter = update_c_setprinter(True);
726 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
728 return (uint32)c_setprinter;
731 /****************************************************************************
732 Get builtin form struct list.
733 ****************************************************************************/
735 int get_builtin_ntforms(nt_forms_struct **list)
737 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
738 if (!*list) {
739 return 0;
741 return ARRAY_SIZE(default_forms);
744 /****************************************************************************
745 get a builtin form struct
746 ****************************************************************************/
748 bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
750 int i;
751 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
752 for (i=0; i<ARRAY_SIZE(default_forms); i++) {
753 if (strequal(form_name,default_forms[i].name)) {
754 DEBUGADD(6,("Found builtin form %s \n", form_name));
755 memcpy(form,&default_forms[i],sizeof(*form));
756 return true;
760 return false;
763 /****************************************************************************
764 get a form struct list.
765 ****************************************************************************/
767 int get_ntforms(nt_forms_struct **list)
769 TDB_DATA kbuf, newkey, dbuf;
770 nt_forms_struct form;
771 int ret;
772 int i;
773 int n = 0;
775 *list = NULL;
777 for (kbuf = tdb_firstkey(tdb_forms);
778 kbuf.dptr;
779 newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
781 if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
782 continue;
784 dbuf = tdb_fetch(tdb_forms, kbuf);
785 if (!dbuf.dptr)
786 continue;
788 fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
789 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
790 &i, &form.flag, &form.width, &form.length, &form.left,
791 &form.top, &form.right, &form.bottom);
792 SAFE_FREE(dbuf.dptr);
793 if (ret != dbuf.dsize)
794 continue;
796 *list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
797 if (!*list) {
798 DEBUG(0,("get_ntforms: Realloc fail.\n"));
799 return 0;
801 (*list)[n] = form;
802 n++;
806 return n;
809 /****************************************************************************
810 write a form struct list
811 ****************************************************************************/
813 int write_ntforms(nt_forms_struct **list, int number)
815 TALLOC_CTX *ctx = talloc_tos();
816 char *buf = NULL;
817 char *key = NULL;
818 int len;
819 TDB_DATA dbuf;
820 int i;
822 for (i=0;i<number;i++) {
823 /* save index, so list is rebuilt in correct order */
824 len = tdb_pack(NULL, 0, "dddddddd",
825 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
826 (*list)[i].left, (*list)[i].top, (*list)[i].right,
827 (*list)[i].bottom);
828 if (!len) {
829 continue;
831 buf = TALLOC_ARRAY(ctx, char, len);
832 if (!buf) {
833 return 0;
835 len = tdb_pack((uint8 *)buf, len, "dddddddd",
836 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
837 (*list)[i].left, (*list)[i].top, (*list)[i].right,
838 (*list)[i].bottom);
839 key = talloc_asprintf(ctx, "%s%s", FORMS_PREFIX, (*list)[i].name);
840 if (!key) {
841 return 0;
843 dbuf.dsize = len;
844 dbuf.dptr = (uint8 *)buf;
845 if (tdb_store_bystring(tdb_forms, key, dbuf, TDB_REPLACE) != 0) {
846 TALLOC_FREE(key);
847 TALLOC_FREE(buf);
848 break;
850 TALLOC_FREE(key);
851 TALLOC_FREE(buf);
854 return i;
857 /****************************************************************************
858 add a form struct at the end of the list
859 ****************************************************************************/
860 bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
862 int n=0;
863 bool update;
866 * NT tries to add forms even when
867 * they are already in the base
868 * only update the values if already present
871 update=False;
873 for (n=0; n<*count; n++) {
874 if ( strequal((*list)[n].name, form->form_name) ) {
875 update=True;
876 break;
880 if (update==False) {
881 if((*list=SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1)) == NULL) {
882 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
883 return False;
885 fstrcpy((*list)[n].name, form->form_name);
886 (*count)++;
889 (*list)[n].flag = form->flags;
890 (*list)[n].width = form->size.width;
891 (*list)[n].length = form->size.height;
892 (*list)[n].left = form->area.left;
893 (*list)[n].top = form->area.top;
894 (*list)[n].right = form->area.right;
895 (*list)[n].bottom = form->area.bottom;
897 DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
898 update ? "updated" : "added", form->form_name));
900 return True;
903 /****************************************************************************
904 Delete a named form struct.
905 ****************************************************************************/
907 bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
909 char *key = NULL;
910 int n=0;
912 *ret = WERR_OK;
914 for (n=0; n<*count; n++) {
915 if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
916 DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
917 break;
921 if (n == *count) {
922 DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
923 *ret = WERR_INVALID_FORM_NAME;
924 return False;
927 if (asprintf(&key, "%s%s", FORMS_PREFIX, (*list)[n].name) < 0) {
928 *ret = WERR_NOMEM;
929 return false;
931 if (tdb_delete_bystring(tdb_forms, key) != 0) {
932 SAFE_FREE(key);
933 *ret = WERR_NOMEM;
934 return False;
936 SAFE_FREE(key);
937 return true;
940 /****************************************************************************
941 Update a form struct.
942 ****************************************************************************/
944 void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
946 int n=0;
948 DEBUG(106, ("[%s]\n", form->form_name));
949 for (n=0; n<count; n++) {
950 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
951 if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
952 break;
955 if (n==count) return;
957 (*list)[n].flag = form->flags;
958 (*list)[n].width = form->size.width;
959 (*list)[n].length = form->size.height;
960 (*list)[n].left = form->area.left;
961 (*list)[n].top = form->area.top;
962 (*list)[n].right = form->area.right;
963 (*list)[n].bottom = form->area.bottom;
966 /****************************************************************************
967 Get the nt drivers list.
968 Traverse the database and look-up the matching names.
969 ****************************************************************************/
970 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
972 int total=0;
973 const char *short_archi;
974 char *key = NULL;
975 TDB_DATA kbuf, newkey;
977 short_archi = get_short_archi(architecture);
978 if (!short_archi) {
979 return 0;
982 if (asprintf(&key, "%s%s/%d/", DRIVERS_PREFIX,
983 short_archi, version) < 0) {
984 return 0;
987 for (kbuf = tdb_firstkey(tdb_drivers);
988 kbuf.dptr;
989 newkey = tdb_nextkey(tdb_drivers, kbuf), free(kbuf.dptr), kbuf=newkey) {
991 if (strncmp((const char *)kbuf.dptr, key, strlen(key)) != 0)
992 continue;
994 if((*list = SMB_REALLOC_ARRAY(*list, fstring, total+1)) == NULL) {
995 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
996 SAFE_FREE(key);
997 return -1;
1000 fstrcpy((*list)[total], (const char *)kbuf.dptr+strlen(key));
1001 total++;
1004 SAFE_FREE(key);
1005 return(total);
1008 /****************************************************************************
1009 Function to do the mapping between the long architecture name and
1010 the short one.
1011 ****************************************************************************/
1013 const char *get_short_archi(const char *long_archi)
1015 int i=-1;
1017 DEBUG(107,("Getting architecture dependant directory\n"));
1018 do {
1019 i++;
1020 } while ( (archi_table[i].long_archi!=NULL ) &&
1021 StrCaseCmp(long_archi, archi_table[i].long_archi) );
1023 if (archi_table[i].long_archi==NULL) {
1024 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
1025 return NULL;
1028 /* this might be client code - but shouldn't this be an fstrcpy etc? */
1030 DEBUGADD(108,("index: [%d]\n", i));
1031 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
1032 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
1034 return archi_table[i].short_archi;
1037 /****************************************************************************
1038 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
1039 There are two case to be covered here: PE (Portable Executable) and NE (New
1040 Executable) files. Both files support the same INFO structure, but PE files
1041 store the signature in unicode, and NE files store it as !unicode.
1042 returns -1 on error, 1 on version info found, and 0 on no version info found.
1043 ****************************************************************************/
1045 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
1047 int i;
1048 char *buf = NULL;
1049 ssize_t byte_count;
1051 if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
1052 DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
1053 fname, DOS_HEADER_SIZE));
1054 goto error_exit;
1057 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
1058 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
1059 fname, (unsigned long)byte_count));
1060 goto no_version_info;
1063 /* Is this really a DOS header? */
1064 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
1065 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
1066 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
1067 goto no_version_info;
1070 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
1071 if (SMB_VFS_LSEEK(fsp, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
1072 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
1073 fname, errno));
1074 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1075 goto no_version_info;
1078 /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
1079 if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
1080 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
1081 fname, (unsigned long)byte_count));
1082 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1083 goto no_version_info;
1086 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
1087 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
1088 unsigned int num_sections;
1089 unsigned int section_table_bytes;
1091 /* Just skip over optional header to get to section table */
1092 if (SMB_VFS_LSEEK(fsp,
1093 SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
1094 SEEK_CUR) == (SMB_OFF_T)-1) {
1095 DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
1096 fname, errno));
1097 goto error_exit;
1100 /* get the section table */
1101 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
1102 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
1103 if (section_table_bytes == 0)
1104 goto error_exit;
1106 SAFE_FREE(buf);
1107 if ((buf=(char *)SMB_MALLOC(section_table_bytes)) == NULL) {
1108 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
1109 fname, section_table_bytes));
1110 goto error_exit;
1113 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
1114 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
1115 fname, (unsigned long)byte_count));
1116 goto error_exit;
1119 /* Iterate the section table looking for the resource section ".rsrc" */
1120 for (i = 0; i < num_sections; i++) {
1121 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
1123 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
1124 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
1125 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
1127 if (section_bytes == 0)
1128 goto error_exit;
1130 SAFE_FREE(buf);
1131 if ((buf=(char *)SMB_MALLOC(section_bytes)) == NULL) {
1132 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
1133 fname, section_bytes));
1134 goto error_exit;
1137 /* Seek to the start of the .rsrc section info */
1138 if (SMB_VFS_LSEEK(fsp, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
1139 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
1140 fname, errno));
1141 goto error_exit;
1144 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
1145 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
1146 fname, (unsigned long)byte_count));
1147 goto error_exit;
1150 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
1151 goto error_exit;
1153 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
1154 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
1155 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
1156 /* Align to next long address */
1157 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
1159 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
1160 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
1161 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
1163 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1164 fname, *major, *minor,
1165 (*major>>16)&0xffff, *major&0xffff,
1166 (*minor>>16)&0xffff, *minor&0xffff));
1167 SAFE_FREE(buf);
1168 return 1;
1175 /* Version info not found, fall back to origin date/time */
1176 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
1177 SAFE_FREE(buf);
1178 return 0;
1180 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
1181 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
1182 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
1183 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
1184 /* At this point, we assume the file is in error. It still could be somthing
1185 * else besides a NE file, but it unlikely at this point. */
1186 goto error_exit;
1189 /* Allocate a bit more space to speed up things */
1190 SAFE_FREE(buf);
1191 if ((buf=(char *)SMB_MALLOC(VS_NE_BUF_SIZE)) == NULL) {
1192 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
1193 fname, PE_HEADER_SIZE));
1194 goto error_exit;
1197 /* This is a HACK! I got tired of trying to sort through the messy
1198 * 'NE' file format. If anyone wants to clean this up please have at
1199 * it, but this works. 'NE' files will eventually fade away. JRR */
1200 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
1201 /* Cover case that should not occur in a well formed 'NE' .dll file */
1202 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
1204 for(i=0; i<byte_count; i++) {
1205 /* Fast skip past data that can't possibly match */
1206 if (buf[i] != 'V') continue;
1208 /* Potential match data crosses buf boundry, move it to beginning
1209 * of buf, and fill the buf with as much as it will hold. */
1210 if (i>byte_count-VS_VERSION_INFO_SIZE) {
1211 int bc;
1213 memcpy(buf, &buf[i], byte_count-i);
1214 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
1215 (byte_count-i))) < 0) {
1217 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
1218 fname, errno));
1219 goto error_exit;
1222 byte_count = bc + (byte_count - i);
1223 if (byte_count<VS_VERSION_INFO_SIZE) break;
1225 i = 0;
1228 /* Check that the full signature string and the magic number that
1229 * follows exist (not a perfect solution, but the chances that this
1230 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
1231 * twice, as it is simpler to read the code. */
1232 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
1233 /* Compute skip alignment to next long address */
1234 int skip = -(SMB_VFS_LSEEK(fsp, 0, SEEK_CUR) - (byte_count - i) +
1235 sizeof(VS_SIGNATURE)) & 3;
1236 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
1238 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
1239 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
1240 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
1241 fname, *major, *minor,
1242 (*major>>16)&0xffff, *major&0xffff,
1243 (*minor>>16)&0xffff, *minor&0xffff));
1244 SAFE_FREE(buf);
1245 return 1;
1250 /* Version info not found, fall back to origin date/time */
1251 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
1252 SAFE_FREE(buf);
1253 return 0;
1255 } else
1256 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
1257 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
1258 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
1260 no_version_info:
1261 SAFE_FREE(buf);
1262 return 0;
1264 error_exit:
1265 SAFE_FREE(buf);
1266 return -1;
1269 /****************************************************************************
1270 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
1271 share one or more files. During the MS installation process files are checked
1272 to insure that only a newer version of a shared file is installed over an
1273 older version. There are several possibilities for this comparison. If there
1274 is no previous version, the new one is newer (obviously). If either file is
1275 missing the version info structure, compare the creation date (on Unix use
1276 the modification date). Otherwise chose the numerically larger version number.
1277 ****************************************************************************/
1279 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
1281 bool use_version = true;
1283 uint32 new_major;
1284 uint32 new_minor;
1285 time_t new_create_time;
1287 uint32 old_major;
1288 uint32 old_minor;
1289 time_t old_create_time;
1291 struct smb_filename *smb_fname = NULL;
1292 files_struct *fsp = NULL;
1293 SMB_STRUCT_STAT st;
1295 NTSTATUS status;
1296 int ret;
1298 SET_STAT_INVALID(st);
1299 new_create_time = (time_t)0;
1300 old_create_time = (time_t)0;
1302 /* Get file version info (if available) for previous file (if it exists) */
1303 status = driver_unix_convert(conn, old_file, &smb_fname);
1304 if (!NT_STATUS_IS_OK(status)) {
1305 goto error_exit;
1308 status = SMB_VFS_CREATE_FILE(
1309 conn, /* conn */
1310 NULL, /* req */
1311 0, /* root_dir_fid */
1312 smb_fname, /* fname */
1313 FILE_GENERIC_READ, /* access_mask */
1314 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1315 FILE_OPEN, /* create_disposition*/
1316 0, /* create_options */
1317 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1318 INTERNAL_OPEN_ONLY, /* oplock_request */
1319 0, /* allocation_size */
1320 0, /* private_flags */
1321 NULL, /* sd */
1322 NULL, /* ea_list */
1323 &fsp, /* result */
1324 NULL); /* pinfo */
1326 if (!NT_STATUS_IS_OK(status)) {
1327 /* Old file not found, so by definition new file is in fact newer */
1328 DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
1329 "errno = %d\n", smb_fname_str_dbg(smb_fname),
1330 errno));
1331 ret = 1;
1332 goto done;
1334 } else {
1335 ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1336 if (ret == -1) {
1337 goto error_exit;
1340 if (!ret) {
1341 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1342 old_file));
1343 use_version = false;
1344 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1345 goto error_exit;
1347 old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1348 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1349 (long)old_create_time));
1352 close_file(NULL, fsp, NORMAL_CLOSE);
1353 fsp = NULL;
1355 /* Get file version info (if available) for new file */
1356 status = driver_unix_convert(conn, new_file, &smb_fname);
1357 if (!NT_STATUS_IS_OK(status)) {
1358 goto error_exit;
1361 status = SMB_VFS_CREATE_FILE(
1362 conn, /* conn */
1363 NULL, /* req */
1364 0, /* root_dir_fid */
1365 smb_fname, /* fname */
1366 FILE_GENERIC_READ, /* access_mask */
1367 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1368 FILE_OPEN, /* create_disposition*/
1369 0, /* create_options */
1370 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1371 INTERNAL_OPEN_ONLY, /* oplock_request */
1372 0, /* allocation_size */
1373 0, /* private_flags */
1374 NULL, /* sd */
1375 NULL, /* ea_list */
1376 &fsp, /* result */
1377 NULL); /* pinfo */
1379 if (!NT_STATUS_IS_OK(status)) {
1380 /* New file not found, this shouldn't occur if the caller did its job */
1381 DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
1382 "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
1383 goto error_exit;
1385 } else {
1386 ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1387 if (ret == -1) {
1388 goto error_exit;
1391 if (!ret) {
1392 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1393 new_file));
1394 use_version = false;
1395 if (SMB_VFS_FSTAT(fsp, &st) == -1) {
1396 goto error_exit;
1398 new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
1399 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
1400 (long)new_create_time));
1403 close_file(NULL, fsp, NORMAL_CLOSE);
1404 fsp = NULL;
1406 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1407 /* Compare versions and choose the larger version number */
1408 if (new_major > old_major ||
1409 (new_major == old_major && new_minor > old_minor)) {
1411 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1412 ret = 1;
1413 goto done;
1415 else {
1416 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1417 ret = 0;
1418 goto done;
1421 } else {
1422 /* Compare modification time/dates and choose the newest time/date */
1423 if (new_create_time > old_create_time) {
1424 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1425 ret = 1;
1426 goto done;
1428 else {
1429 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1430 ret = 0;
1431 goto done;
1435 error_exit:
1436 if(fsp)
1437 close_file(NULL, fsp, NORMAL_CLOSE);
1438 ret = -1;
1439 done:
1440 TALLOC_FREE(smb_fname);
1441 return ret;
1444 /****************************************************************************
1445 Determine the correct cVersion associated with an architecture and driver
1446 ****************************************************************************/
1447 static uint32 get_correct_cversion(struct pipes_struct *p,
1448 const char *architecture,
1449 const char *driverpath_in,
1450 WERROR *perr)
1452 int cversion;
1453 NTSTATUS nt_status;
1454 struct smb_filename *smb_fname = NULL;
1455 char *driverpath = NULL;
1456 files_struct *fsp = NULL;
1457 connection_struct *conn = NULL;
1458 NTSTATUS status;
1459 char *oldcwd;
1460 fstring printdollar;
1461 int printdollar_snum;
1463 *perr = WERR_INVALID_PARAM;
1465 /* If architecture is Windows 95/98/ME, the version is always 0. */
1466 if (strcmp(architecture, SPL_ARCH_WIN40) == 0) {
1467 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1468 *perr = WERR_OK;
1469 return 0;
1472 /* If architecture is Windows x64, the version is always 3. */
1473 if (strcmp(architecture, SPL_ARCH_X64) == 0) {
1474 DEBUG(10,("get_correct_cversion: Driver is x64, cversion = 3\n"));
1475 *perr = WERR_OK;
1476 return 3;
1479 fstrcpy(printdollar, "print$");
1481 printdollar_snum = find_service(printdollar);
1482 if (printdollar_snum == -1) {
1483 *perr = WERR_NO_SUCH_SHARE;
1484 return -1;
1487 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1488 lp_pathname(printdollar_snum),
1489 p->server_info, &oldcwd);
1490 if (!NT_STATUS_IS_OK(nt_status)) {
1491 DEBUG(0,("get_correct_cversion: create_conn_struct "
1492 "returned %s\n", nt_errstr(nt_status)));
1493 *perr = ntstatus_to_werror(nt_status);
1494 return -1;
1497 /* Open the driver file (Portable Executable format) and determine the
1498 * deriver the cversion. */
1499 driverpath = talloc_asprintf(talloc_tos(),
1500 "%s/%s",
1501 architecture,
1502 driverpath_in);
1503 if (!driverpath) {
1504 *perr = WERR_NOMEM;
1505 goto error_exit;
1508 nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
1509 if (!NT_STATUS_IS_OK(nt_status)) {
1510 *perr = ntstatus_to_werror(nt_status);
1511 goto error_exit;
1514 nt_status = vfs_file_exist(conn, smb_fname);
1515 if (!NT_STATUS_IS_OK(nt_status)) {
1516 *perr = WERR_BADFILE;
1517 goto error_exit;
1520 status = SMB_VFS_CREATE_FILE(
1521 conn, /* conn */
1522 NULL, /* req */
1523 0, /* root_dir_fid */
1524 smb_fname, /* fname */
1525 FILE_GENERIC_READ, /* access_mask */
1526 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
1527 FILE_OPEN, /* create_disposition*/
1528 0, /* create_options */
1529 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
1530 INTERNAL_OPEN_ONLY, /* oplock_request */
1531 0, /* private_flags */
1532 0, /* allocation_size */
1533 NULL, /* sd */
1534 NULL, /* ea_list */
1535 &fsp, /* result */
1536 NULL); /* pinfo */
1538 if (!NT_STATUS_IS_OK(status)) {
1539 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
1540 "%d\n", smb_fname_str_dbg(smb_fname), errno));
1541 *perr = WERR_ACCESS_DENIED;
1542 goto error_exit;
1543 } else {
1544 uint32 major;
1545 uint32 minor;
1546 int ret;
1548 ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
1549 if (ret == -1) goto error_exit;
1551 if (!ret) {
1552 DEBUG(6,("get_correct_cversion: Version info not "
1553 "found [%s]\n",
1554 smb_fname_str_dbg(smb_fname)));
1555 goto error_exit;
1559 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1560 * for more details. Version in this case is not just the version of the
1561 * file, but the version in the sense of kernal mode (2) vs. user mode
1562 * (3) drivers. Other bits of the version fields are the version info.
1563 * JRR 010716
1565 cversion = major & 0x0000ffff;
1566 switch (cversion) {
1567 case 2: /* WinNT drivers */
1568 case 3: /* Win2K drivers */
1569 break;
1571 default:
1572 DEBUG(6,("get_correct_cversion: cversion "
1573 "invalid [%s] cversion = %d\n",
1574 smb_fname_str_dbg(smb_fname),
1575 cversion));
1576 goto error_exit;
1579 DEBUG(10,("get_correct_cversion: Version info found [%s] major"
1580 " = 0x%x minor = 0x%x\n",
1581 smb_fname_str_dbg(smb_fname), major, minor));
1584 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1585 smb_fname_str_dbg(smb_fname), cversion));
1587 goto done;
1589 error_exit:
1590 cversion = -1;
1591 done:
1592 TALLOC_FREE(smb_fname);
1593 if (fsp != NULL) {
1594 close_file(NULL, fsp, NORMAL_CLOSE);
1596 if (conn != NULL) {
1597 vfs_ChDir(conn, oldcwd);
1598 conn_free(conn);
1600 if (cversion != -1) {
1601 *perr = WERR_OK;
1603 return cversion;
1606 /****************************************************************************
1607 ****************************************************************************/
1609 #define strip_driver_path(_mem_ctx, _element) do { \
1610 if (_element && ((_p = strrchr((_element), '\\')) != NULL)) { \
1611 (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
1612 W_ERROR_HAVE_NO_MEMORY((_element)); \
1614 } while (0);
1616 static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
1617 struct pipes_struct *rpc_pipe,
1618 const char *architecture,
1619 const char **driver_path,
1620 const char **data_file,
1621 const char **config_file,
1622 const char **help_file,
1623 struct spoolss_StringArray *dependent_files,
1624 uint32_t *version)
1626 const char *short_architecture;
1627 int i;
1628 WERROR err;
1629 char *_p;
1631 if (!*driver_path || !*data_file || !*config_file) {
1632 return WERR_INVALID_PARAM;
1635 /* clean up the driver name.
1636 * we can get .\driver.dll
1637 * or worse c:\windows\system\driver.dll !
1639 /* using an intermediate string to not have overlaping memcpy()'s */
1641 strip_driver_path(mem_ctx, *driver_path);
1642 strip_driver_path(mem_ctx, *data_file);
1643 strip_driver_path(mem_ctx, *config_file);
1644 if (help_file) {
1645 strip_driver_path(mem_ctx, *help_file);
1648 if (dependent_files && dependent_files->string) {
1649 for (i=0; dependent_files->string[i]; i++) {
1650 strip_driver_path(mem_ctx, dependent_files->string[i]);
1654 short_architecture = get_short_archi(architecture);
1655 if (!short_architecture) {
1656 return WERR_UNKNOWN_PRINTER_DRIVER;
1659 /* jfm:7/16/2000 the client always sends the cversion=0.
1660 * The server should check which version the driver is by reading
1661 * the PE header of driver->driverpath.
1663 * For Windows 95/98 the version is 0 (so the value sent is correct)
1664 * For Windows NT (the architecture doesn't matter)
1665 * NT 3.1: cversion=0
1666 * NT 3.5/3.51: cversion=1
1667 * NT 4: cversion=2
1668 * NT2K: cversion=3
1671 *version = get_correct_cversion(rpc_pipe, short_architecture,
1672 *driver_path, &err);
1673 if (*version == -1) {
1674 return err;
1677 return WERR_OK;
1680 /****************************************************************************
1681 ****************************************************************************/
1683 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
1684 struct spoolss_AddDriverInfoCtr *r)
1686 switch (r->level) {
1687 case 3:
1688 return clean_up_driver_struct_level(r, rpc_pipe,
1689 r->info.info3->architecture,
1690 &r->info.info3->driver_path,
1691 &r->info.info3->data_file,
1692 &r->info.info3->config_file,
1693 &r->info.info3->help_file,
1694 r->info.info3->dependent_files,
1695 &r->info.info3->version);
1696 case 6:
1697 return clean_up_driver_struct_level(r, rpc_pipe,
1698 r->info.info6->architecture,
1699 &r->info.info6->driver_path,
1700 &r->info.info6->data_file,
1701 &r->info.info6->config_file,
1702 &r->info.info6->help_file,
1703 r->info.info6->dependent_files,
1704 &r->info.info6->version);
1705 default:
1706 return WERR_NOT_SUPPORTED;
1710 /****************************************************************************
1711 This function sucks and should be replaced. JRA.
1712 ****************************************************************************/
1714 static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
1715 const struct spoolss_AddDriverInfo6 *src)
1717 dst->version = src->version;
1719 dst->driver_name = src->driver_name;
1720 dst->architecture = src->architecture;
1721 dst->driver_path = src->driver_path;
1722 dst->data_file = src->data_file;
1723 dst->config_file = src->config_file;
1724 dst->help_file = src->help_file;
1725 dst->monitor_name = src->monitor_name;
1726 dst->default_datatype = src->default_datatype;
1727 dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
1728 dst->dependent_files = src->dependent_files;
1731 /****************************************************************************
1732 This function sucks and should be replaced. JRA.
1733 ****************************************************************************/
1735 static void convert_level_8_to_level3(TALLOC_CTX *mem_ctx,
1736 struct spoolss_AddDriverInfo3 *dst,
1737 const struct spoolss_DriverInfo8 *src)
1739 dst->version = src->version;
1740 dst->driver_name = src->driver_name;
1741 dst->architecture = src->architecture;
1742 dst->driver_path = src->driver_path;
1743 dst->data_file = src->data_file;
1744 dst->config_file = src->config_file;
1745 dst->help_file = src->help_file;
1746 dst->monitor_name = src->monitor_name;
1747 dst->default_datatype = src->default_datatype;
1748 if (src->dependent_files) {
1749 dst->dependent_files = talloc_zero(mem_ctx, struct spoolss_StringArray);
1750 if (!dst->dependent_files) return;
1751 dst->dependent_files->string = src->dependent_files;
1752 } else {
1753 dst->dependent_files = NULL;
1757 /****************************************************************************
1758 ****************************************************************************/
1760 static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
1761 connection_struct *conn,
1762 const char *driver_file,
1763 const char *short_architecture,
1764 uint32_t driver_version,
1765 uint32_t version)
1767 struct smb_filename *smb_fname_old = NULL;
1768 struct smb_filename *smb_fname_new = NULL;
1769 char *old_name = NULL;
1770 char *new_name = NULL;
1771 NTSTATUS status;
1772 WERROR ret;
1774 old_name = talloc_asprintf(mem_ctx, "%s/%s",
1775 short_architecture, driver_file);
1776 W_ERROR_HAVE_NO_MEMORY(old_name);
1778 new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
1779 short_architecture, driver_version, driver_file);
1780 if (new_name == NULL) {
1781 TALLOC_FREE(old_name);
1782 return WERR_NOMEM;
1785 if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
1787 status = driver_unix_convert(conn, old_name, &smb_fname_old);
1788 if (!NT_STATUS_IS_OK(status)) {
1789 ret = WERR_NOMEM;
1790 goto out;
1793 /* Setup a synthetic smb_filename struct */
1794 smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
1795 if (!smb_fname_new) {
1796 ret = WERR_NOMEM;
1797 goto out;
1800 smb_fname_new->base_name = new_name;
1802 DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
1803 "'%s'\n", smb_fname_old->base_name,
1804 smb_fname_new->base_name));
1806 status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
1807 OPENX_FILE_EXISTS_TRUNCATE |
1808 OPENX_FILE_CREATE_IF_NOT_EXIST,
1809 0, false);
1811 if (!NT_STATUS_IS_OK(status)) {
1812 DEBUG(0,("move_driver_file_to_download_area: Unable "
1813 "to rename [%s] to [%s]: %s\n",
1814 smb_fname_old->base_name, new_name,
1815 nt_errstr(status)));
1816 ret = WERR_ACCESS_DENIED;
1817 goto out;
1821 ret = WERR_OK;
1822 out:
1823 TALLOC_FREE(smb_fname_old);
1824 TALLOC_FREE(smb_fname_new);
1825 return ret;
1828 WERROR move_driver_to_download_area(struct pipes_struct *p,
1829 struct spoolss_AddDriverInfoCtr *r,
1830 WERROR *perr)
1832 struct spoolss_AddDriverInfo3 *driver;
1833 struct spoolss_AddDriverInfo3 converted_driver;
1834 const char *short_architecture;
1835 struct smb_filename *smb_dname = NULL;
1836 char *new_dir = NULL;
1837 connection_struct *conn = NULL;
1838 NTSTATUS nt_status;
1839 int i;
1840 TALLOC_CTX *ctx = talloc_tos();
1841 int ver = 0;
1842 char *oldcwd;
1843 fstring printdollar;
1844 int printdollar_snum;
1846 *perr = WERR_OK;
1848 switch (r->level) {
1849 case 3:
1850 driver = r->info.info3;
1851 break;
1852 case 6:
1853 convert_level_6_to_level3(&converted_driver, r->info.info6);
1854 driver = &converted_driver;
1855 break;
1856 default:
1857 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
1858 return WERR_UNKNOWN_LEVEL;
1861 short_architecture = get_short_archi(driver->architecture);
1862 if (!short_architecture) {
1863 return WERR_UNKNOWN_PRINTER_DRIVER;
1866 fstrcpy(printdollar, "print$");
1868 printdollar_snum = find_service(printdollar);
1869 if (printdollar_snum == -1) {
1870 *perr = WERR_NO_SUCH_SHARE;
1871 return WERR_NO_SUCH_SHARE;
1874 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
1875 lp_pathname(printdollar_snum),
1876 p->server_info, &oldcwd);
1877 if (!NT_STATUS_IS_OK(nt_status)) {
1878 DEBUG(0,("move_driver_to_download_area: create_conn_struct "
1879 "returned %s\n", nt_errstr(nt_status)));
1880 *perr = ntstatus_to_werror(nt_status);
1881 return *perr;
1884 new_dir = talloc_asprintf(ctx,
1885 "%s/%d",
1886 short_architecture,
1887 driver->version);
1888 if (!new_dir) {
1889 *perr = WERR_NOMEM;
1890 goto err_exit;
1892 nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
1893 if (!NT_STATUS_IS_OK(nt_status)) {
1894 *perr = WERR_NOMEM;
1895 goto err_exit;
1898 DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
1900 create_directory(conn, NULL, smb_dname);
1902 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1903 * listed for this driver which has already been moved, skip it (note:
1904 * drivers may list the same file name several times. Then check if the
1905 * file already exists in archi\version\, if so, check that the version
1906 * info (or time stamps if version info is unavailable) is newer (or the
1907 * date is later). If it is, move it to archi\version\filexxx.yyy.
1908 * Otherwise, delete the file.
1910 * If a file is not moved to archi\version\ because of an error, all the
1911 * rest of the 'unmoved' driver files are removed from archi\. If one or
1912 * more of the driver's files was already moved to archi\version\, it
1913 * potentially leaves the driver in a partially updated state. Version
1914 * trauma will most likely occur if an client attempts to use any printer
1915 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1916 * done is appropriate... later JRR
1919 DEBUG(5,("Moving files now !\n"));
1921 if (driver->driver_path && strlen(driver->driver_path)) {
1923 *perr = move_driver_file_to_download_area(ctx,
1924 conn,
1925 driver->driver_path,
1926 short_architecture,
1927 driver->version,
1928 ver);
1929 if (!W_ERROR_IS_OK(*perr)) {
1930 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1931 ver = -1;
1933 goto err_exit;
1937 if (driver->data_file && strlen(driver->data_file)) {
1938 if (!strequal(driver->data_file, driver->driver_path)) {
1940 *perr = move_driver_file_to_download_area(ctx,
1941 conn,
1942 driver->data_file,
1943 short_architecture,
1944 driver->version,
1945 ver);
1946 if (!W_ERROR_IS_OK(*perr)) {
1947 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1948 ver = -1;
1950 goto err_exit;
1955 if (driver->config_file && strlen(driver->config_file)) {
1956 if (!strequal(driver->config_file, driver->driver_path) &&
1957 !strequal(driver->config_file, driver->data_file)) {
1959 *perr = move_driver_file_to_download_area(ctx,
1960 conn,
1961 driver->config_file,
1962 short_architecture,
1963 driver->version,
1964 ver);
1965 if (!W_ERROR_IS_OK(*perr)) {
1966 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1967 ver = -1;
1969 goto err_exit;
1974 if (driver->help_file && strlen(driver->help_file)) {
1975 if (!strequal(driver->help_file, driver->driver_path) &&
1976 !strequal(driver->help_file, driver->data_file) &&
1977 !strequal(driver->help_file, driver->config_file)) {
1979 *perr = move_driver_file_to_download_area(ctx,
1980 conn,
1981 driver->help_file,
1982 short_architecture,
1983 driver->version,
1984 ver);
1985 if (!W_ERROR_IS_OK(*perr)) {
1986 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
1987 ver = -1;
1989 goto err_exit;
1994 if (driver->dependent_files && driver->dependent_files->string) {
1995 for (i=0; driver->dependent_files->string[i]; i++) {
1996 if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
1997 !strequal(driver->dependent_files->string[i], driver->data_file) &&
1998 !strequal(driver->dependent_files->string[i], driver->config_file) &&
1999 !strequal(driver->dependent_files->string[i], driver->help_file)) {
2000 int j;
2001 for (j=0; j < i; j++) {
2002 if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
2003 goto NextDriver;
2007 *perr = move_driver_file_to_download_area(ctx,
2008 conn,
2009 driver->dependent_files->string[i],
2010 short_architecture,
2011 driver->version,
2012 ver);
2013 if (!W_ERROR_IS_OK(*perr)) {
2014 if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
2015 ver = -1;
2017 goto err_exit;
2020 NextDriver: ;
2024 err_exit:
2025 TALLOC_FREE(smb_dname);
2027 if (conn != NULL) {
2028 vfs_ChDir(conn, oldcwd);
2029 conn_free(conn);
2032 if (W_ERROR_EQUAL(*perr, WERR_OK)) {
2033 return WERR_OK;
2035 if (ver == -1) {
2036 return WERR_UNKNOWN_PRINTER_DRIVER;
2038 return (*perr);
2041 /****************************************************************************
2042 ****************************************************************************/
2044 static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
2046 TALLOC_CTX *ctx = talloc_tos();
2047 int len, buflen;
2048 const char *architecture;
2049 char *directory = NULL;
2050 char *key = NULL;
2051 uint8 *buf;
2052 int i, ret;
2053 TDB_DATA dbuf;
2055 architecture = get_short_archi(driver->architecture);
2056 if (!architecture) {
2057 return (uint32)-1;
2060 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
2061 * \\server is added in the rpc server layer.
2062 * It does make sense to NOT store the server's name in the printer TDB.
2065 directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
2066 architecture, driver->version);
2067 if (!directory) {
2068 return (uint32)-1;
2071 #define gen_full_driver_unc_path(ctx, directory, file) \
2072 do { \
2073 if (file && strlen(file)) { \
2074 file = talloc_asprintf(ctx, "%s%s", directory, file); \
2075 } else { \
2076 file = talloc_strdup(ctx, ""); \
2078 if (!file) { \
2079 return (uint32_t)-1; \
2081 } while (0);
2083 /* .inf files do not always list a file for each of the four standard files.
2084 * Don't prepend a path to a null filename, or client claims:
2085 * "The server on which the printer resides does not have a suitable
2086 * <printer driver name> printer driver installed. Click OK if you
2087 * wish to install the driver on your local machine."
2090 gen_full_driver_unc_path(ctx, directory, driver->driver_path);
2091 gen_full_driver_unc_path(ctx, directory, driver->data_file);
2092 gen_full_driver_unc_path(ctx, directory, driver->config_file);
2093 gen_full_driver_unc_path(ctx, directory, driver->help_file);
2095 if (driver->dependent_files && driver->dependent_files->string) {
2096 for (i=0; driver->dependent_files->string[i]; i++) {
2097 gen_full_driver_unc_path(ctx, directory,
2098 driver->dependent_files->string[i]);
2102 key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
2103 architecture, driver->version, driver->driver_name);
2104 if (!key) {
2105 return (uint32)-1;
2108 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
2110 buf = NULL;
2111 len = buflen = 0;
2113 again:
2114 len = 0;
2115 len += tdb_pack(buf+len, buflen-len, "dffffffff",
2116 driver->version,
2117 driver->driver_name,
2118 driver->architecture,
2119 driver->driver_path,
2120 driver->data_file,
2121 driver->config_file,
2122 driver->help_file,
2123 driver->monitor_name ? driver->monitor_name : "",
2124 driver->default_datatype ? driver->default_datatype : "");
2126 if (driver->dependent_files && driver->dependent_files->string) {
2127 for (i=0; driver->dependent_files->string[i]; i++) {
2128 len += tdb_pack(buf+len, buflen-len, "f",
2129 driver->dependent_files->string[i]);
2133 if (len != buflen) {
2134 buf = (uint8 *)SMB_REALLOC(buf, len);
2135 if (!buf) {
2136 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
2137 ret = -1;
2138 goto done;
2140 buflen = len;
2141 goto again;
2144 dbuf.dptr = buf;
2145 dbuf.dsize = len;
2147 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
2149 done:
2150 if (ret)
2151 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
2153 SAFE_FREE(buf);
2154 return ret;
2157 /****************************************************************************
2158 ****************************************************************************/
2160 static uint32_t add_a_printer_driver_8(struct spoolss_DriverInfo8 *driver)
2162 TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
2163 struct spoolss_AddDriverInfo3 info3;
2164 uint32_t ret;
2166 convert_level_8_to_level3(mem_ctx, &info3, driver);
2168 ret = add_a_printer_driver_3(&info3);
2169 talloc_free(mem_ctx);
2171 return ret;
2174 /****************************************************************************
2175 ****************************************************************************/
2177 static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
2178 struct spoolss_DriverInfo3 *info,
2179 const char *driver, const char *arch)
2181 info->driver_name = talloc_strdup(mem_ctx, driver);
2182 if (!info->driver_name) {
2183 return WERR_NOMEM;
2186 info->default_datatype = talloc_strdup(mem_ctx, "RAW");
2187 if (!info->default_datatype) {
2188 return WERR_NOMEM;
2191 info->driver_path = talloc_strdup(mem_ctx, "");
2192 info->data_file = talloc_strdup(mem_ctx, "");
2193 info->config_file = talloc_strdup(mem_ctx, "");
2194 info->help_file = talloc_strdup(mem_ctx, "");
2195 if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
2196 return WERR_NOMEM;
2199 return WERR_OK;
2202 /****************************************************************************
2203 ****************************************************************************/
2205 static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
2206 struct spoolss_DriverInfo3 *driver,
2207 const char *drivername, const char *arch,
2208 uint32_t version)
2210 TDB_DATA dbuf;
2211 const char *architecture;
2212 int len = 0;
2213 int i;
2214 char *key = NULL;
2215 fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
2217 architecture = get_short_archi(arch);
2218 if ( !architecture ) {
2219 return WERR_UNKNOWN_PRINTER_DRIVER;
2222 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
2224 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
2225 version = 0;
2227 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
2229 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
2230 architecture, version, drivername) < 0) {
2231 return WERR_NOMEM;
2234 dbuf = tdb_fetch_bystring(tdb_drivers, key);
2235 if (!dbuf.dptr) {
2236 SAFE_FREE(key);
2237 return WERR_UNKNOWN_PRINTER_DRIVER;
2240 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
2241 &driver->version,
2242 name,
2243 environment,
2244 driverpath,
2245 datafile,
2246 configfile,
2247 helpfile,
2248 monitorname,
2249 defaultdatatype);
2251 driver->driver_name = talloc_strdup(mem_ctx, name);
2252 driver->architecture = talloc_strdup(mem_ctx, environment);
2253 driver->driver_path = talloc_strdup(mem_ctx, driverpath);
2254 driver->data_file = talloc_strdup(mem_ctx, datafile);
2255 driver->config_file = talloc_strdup(mem_ctx, configfile);
2256 driver->help_file = talloc_strdup(mem_ctx, helpfile);
2257 driver->monitor_name = talloc_strdup(mem_ctx, monitorname);
2258 driver->default_datatype = talloc_strdup(mem_ctx, defaultdatatype);
2260 i=0;
2262 while (len < dbuf.dsize) {
2264 fstring file;
2266 driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
2267 if (!driver->dependent_files ) {
2268 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
2269 break;
2272 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
2273 &file);
2275 driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
2277 i++;
2280 if (driver->dependent_files)
2281 driver->dependent_files[i] = NULL;
2283 SAFE_FREE(dbuf.dptr);
2284 SAFE_FREE(key);
2286 if (len != dbuf.dsize) {
2287 return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
2290 return WERR_OK;
2293 /****************************************************************************
2294 ****************************************************************************/
2295 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
2297 int len = 0;
2299 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
2301 if (!nt_devmode)
2302 return len;
2304 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2305 nt_devmode->devicename,
2306 nt_devmode->formname,
2308 nt_devmode->specversion,
2309 nt_devmode->driverversion,
2310 nt_devmode->size,
2311 nt_devmode->driverextra,
2312 nt_devmode->orientation,
2313 nt_devmode->papersize,
2314 nt_devmode->paperlength,
2315 nt_devmode->paperwidth,
2316 nt_devmode->scale,
2317 nt_devmode->copies,
2318 nt_devmode->defaultsource,
2319 nt_devmode->printquality,
2320 nt_devmode->color,
2321 nt_devmode->duplex,
2322 nt_devmode->yresolution,
2323 nt_devmode->ttoption,
2324 nt_devmode->collate,
2325 nt_devmode->logpixels,
2327 nt_devmode->fields,
2328 nt_devmode->bitsperpel,
2329 nt_devmode->pelswidth,
2330 nt_devmode->pelsheight,
2331 nt_devmode->displayflags,
2332 nt_devmode->displayfrequency,
2333 nt_devmode->icmmethod,
2334 nt_devmode->icmintent,
2335 nt_devmode->mediatype,
2336 nt_devmode->dithertype,
2337 nt_devmode->reserved1,
2338 nt_devmode->reserved2,
2339 nt_devmode->panningwidth,
2340 nt_devmode->panningheight,
2341 nt_devmode->nt_dev_private);
2343 if (nt_devmode->nt_dev_private) {
2344 len += tdb_pack(buf+len, buflen-len, "B",
2345 nt_devmode->driverextra,
2346 nt_devmode->nt_dev_private);
2349 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
2351 return len;
2354 /****************************************************************************
2355 Pack all values in all printer keys
2356 ***************************************************************************/
2358 static int pack_values(NT_PRINTER_DATA *data, uint8 *buf, int buflen)
2360 int len = 0;
2361 int i, j;
2362 struct regval_blob *val;
2363 struct regval_ctr *val_ctr;
2364 char *path = NULL;
2365 int num_values;
2367 if ( !data )
2368 return 0;
2370 /* loop over all keys */
2372 for ( i=0; i<data->num_keys; i++ ) {
2373 val_ctr = data->keys[i].values;
2374 num_values = regval_ctr_numvals( val_ctr );
2376 /* pack the keyname followed by a empty value */
2378 len += tdb_pack(buf+len, buflen-len, "pPdB",
2379 &data->keys[i].name,
2380 data->keys[i].name,
2381 REG_NONE,
2383 NULL);
2385 /* now loop over all values */
2387 for ( j=0; j<num_values; j++ ) {
2388 /* pathname should be stored as <key>\<value> */
2390 val = regval_ctr_specific_value( val_ctr, j );
2391 if (asprintf(&path, "%s\\%s",
2392 data->keys[i].name,
2393 regval_name(val)) < 0) {
2394 return -1;
2397 len += tdb_pack(buf+len, buflen-len, "pPdB",
2398 val,
2399 path,
2400 regval_type(val),
2401 regval_size(val),
2402 regval_data_p(val) );
2404 DEBUG(8,("specific: [%s], len: %d\n", regval_name(val), regval_size(val)));
2405 SAFE_FREE(path);
2410 /* terminator */
2412 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2414 return len;
2418 /****************************************************************************
2419 Delete a printer - this just deletes the printer info file, any open
2420 handles are not affected.
2421 ****************************************************************************/
2423 uint32 del_a_printer(const char *sharename)
2425 TDB_DATA kbuf;
2426 char *printdb_path = NULL;
2427 TALLOC_CTX *ctx = talloc_tos();
2429 kbuf = make_printer_tdbkey(ctx, sharename);
2430 tdb_delete(tdb_printers, kbuf);
2432 kbuf= make_printers_secdesc_tdbkey(ctx, sharename);
2433 tdb_delete(tdb_printers, kbuf);
2435 close_all_print_db();
2437 if (geteuid() == sec_initial_uid()) {
2438 if (asprintf(&printdb_path, "%s%s.tdb",
2439 cache_path("printing/"),
2440 sharename) < 0) {
2441 return (uint32)-1;
2443 unlink(printdb_path);
2444 SAFE_FREE(printdb_path);
2447 return 0;
2450 /****************************************************************************
2451 ****************************************************************************/
2452 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2454 uint8 *buf;
2455 int buflen, len;
2456 int retlen;
2457 WERROR ret;
2458 TDB_DATA kbuf, dbuf;
2461 * in addprinter: no servername and the printer is the name
2462 * in setprinter: servername is \\server
2463 * and printer is \\server\\printer
2465 * Samba manages only local printers.
2466 * we currently don't support things like i
2467 * path=\\other_server\printer
2469 * We only store the printername, not \\server\printername
2472 if ( info->servername[0] != '\0' ) {
2473 trim_string(info->printername, info->servername, NULL);
2474 trim_char(info->printername, '\\', '\0');
2475 info->servername[0]='\0';
2479 * JFM: one day I'll forget.
2480 * below that's info->portname because that's the SAMBA sharename
2481 * and I made NT 'thinks' it's the portname
2482 * the info->sharename is the thing you can name when you add a printer
2483 * that's the short-name when you create shared printer for 95/98
2484 * So I've made a limitation in SAMBA: you can only have 1 printer model
2485 * behind a SAMBA share.
2488 buf = NULL;
2489 buflen = 0;
2491 again:
2492 len = 0;
2493 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2494 info->attributes,
2495 info->priority,
2496 info->default_priority,
2497 info->starttime,
2498 info->untiltime,
2499 info->status,
2500 info->cjobs,
2501 info->averageppm,
2502 info->changeid,
2503 info->c_setprinter,
2504 info->setuptime,
2505 info->servername,
2506 info->printername,
2507 info->sharename,
2508 info->portname,
2509 info->drivername,
2510 info->comment,
2511 info->location,
2512 info->sepfile,
2513 info->printprocessor,
2514 info->datatype,
2515 info->parameters);
2517 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2518 retlen = pack_values( info->data, buf+len, buflen-len );
2519 if (retlen == -1) {
2520 ret = WERR_NOMEM;
2521 goto done;
2523 len += retlen;
2525 if (buflen != len) {
2526 buf = (uint8 *)SMB_REALLOC(buf, len);
2527 if (!buf) {
2528 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2529 ret = WERR_NOMEM;
2530 goto done;
2532 buflen = len;
2533 goto again;
2536 kbuf = make_printer_tdbkey(talloc_tos(), info->sharename );
2538 dbuf.dptr = buf;
2539 dbuf.dsize = len;
2541 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2543 done:
2544 if (!W_ERROR_IS_OK(ret))
2545 DEBUG(8, ("error updating printer to tdb on disk\n"));
2547 SAFE_FREE(buf);
2549 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2550 info->sharename, info->drivername, info->portname, len));
2552 return ret;
2555 /****************************************************************************
2556 Create and allocate a default devicemode.
2557 ****************************************************************************/
2559 WERROR spoolss_create_default_devmode(TALLOC_CTX *mem_ctx,
2560 const char *devicename,
2561 struct spoolss_DeviceMode **devmode)
2563 struct spoolss_DeviceMode *dm;
2564 char *dname;
2566 dm = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
2567 if (dm == NULL) {
2568 return WERR_NOMEM;
2571 dname = talloc_asprintf(dm, "%s", devicename);
2572 if (dname == NULL) {
2573 return WERR_NOMEM;
2575 if (strlen(dname) > MAXDEVICENAME) {
2576 dname[MAXDEVICENAME] = '\0';
2578 dm->devicename = dname;
2580 dm->formname = talloc_strdup(dm, "Letter");
2581 if (dm->formname == NULL) {
2582 return WERR_NOMEM;
2585 dm->specversion = DMSPEC_NT4_AND_ABOVE;
2586 dm->driverversion = 0x0400;
2587 dm->size = 0x00DC;
2588 dm->__driverextra_length = 0;
2589 dm->fields = DEVMODE_FORMNAME |
2590 DEVMODE_TTOPTION |
2591 DEVMODE_PRINTQUALITY |
2592 DEVMODE_DEFAULTSOURCE |
2593 DEVMODE_COPIES |
2594 DEVMODE_SCALE |
2595 DEVMODE_PAPERSIZE |
2596 DEVMODE_ORIENTATION;
2597 dm->orientation = DMORIENT_PORTRAIT;
2598 dm->papersize = DMPAPER_LETTER;
2599 dm->paperlength = 0;
2600 dm->paperwidth = 0;
2601 dm->scale = 0x64;
2602 dm->copies = 1;
2603 dm->defaultsource = DMBIN_FORMSOURCE;
2604 dm->printquality = DMRES_HIGH; /* 0x0258 */
2605 dm->color = DMRES_MONOCHROME;
2606 dm->duplex = DMDUP_SIMPLEX;
2607 dm->yresolution = 0;
2608 dm->ttoption = DMTT_SUBDEV;
2609 dm->collate = DMCOLLATE_FALSE;
2610 dm->icmmethod = 0;
2611 dm->icmintent = 0;
2612 dm->mediatype = 0;
2613 dm->dithertype = 0;
2615 dm->logpixels = 0;
2616 dm->bitsperpel = 0;
2617 dm->pelswidth = 0;
2618 dm->pelsheight = 0;
2619 dm->displayflags = 0;
2620 dm->displayfrequency = 0;
2621 dm->reserved1 = 0;
2622 dm->reserved2 = 0;
2623 dm->panningwidth = 0;
2624 dm->panningheight = 0;
2626 dm->driverextra_data.data = NULL;
2627 dm->driverextra_data.length = 0;
2629 *devmode = dm;
2630 return WERR_OK;
2633 WERROR spoolss_create_default_secdesc(TALLOC_CTX *mem_ctx,
2634 struct spoolss_security_descriptor **secdesc)
2636 SEC_ACE ace[5]; /* max number of ace entries */
2637 int i = 0;
2638 uint32_t sa;
2639 SEC_ACL *psa = NULL;
2640 SEC_DESC *psd = NULL;
2641 DOM_SID adm_sid;
2642 size_t sd_size;
2644 /* Create an ACE where Everyone is allowed to print */
2646 sa = PRINTER_ACE_PRINT;
2647 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2648 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2650 /* Add the domain admins group if we are a DC */
2652 if ( IS_DC ) {
2653 DOM_SID domadmins_sid;
2655 sid_compose(&domadmins_sid, get_global_sam_sid(),
2656 DOMAIN_GROUP_RID_ADMINS);
2658 sa = PRINTER_ACE_FULL_CONTROL;
2659 init_sec_ace(&ace[i++], &domadmins_sid,
2660 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2661 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2662 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2663 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2665 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
2666 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
2668 sa = PRINTER_ACE_FULL_CONTROL;
2669 init_sec_ace(&ace[i++], &adm_sid,
2670 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2671 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2672 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2673 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2676 /* add BUILTIN\Administrators as FULL CONTROL */
2678 sa = PRINTER_ACE_FULL_CONTROL;
2679 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2680 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
2681 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
2682 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
2683 SEC_ACE_TYPE_ACCESS_ALLOWED,
2684 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2686 /* Make the security descriptor owned by the BUILTIN\Administrators */
2688 /* The ACL revision number in rpc_secdesc.h differs from the one
2689 created by NT when setting ACE entries in printer
2690 descriptors. NT4 complains about the property being edited by a
2691 NT5 machine. */
2693 if ((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
2694 psd = make_sec_desc(mem_ctx,
2695 SEC_DESC_REVISION,
2696 SEC_DESC_SELF_RELATIVE,
2697 &global_sid_Builtin_Administrators,
2698 &global_sid_Builtin_Administrators,
2699 NULL,
2700 psa,
2701 &sd_size);
2704 if (psd == NULL) {
2705 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2706 return WERR_NOMEM;
2709 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2710 (unsigned int)sd_size));
2712 *secdesc = psd;
2714 return WERR_OK;
2717 /****************************************************************************
2718 Malloc and return an NT devicemode.
2719 ****************************************************************************/
2721 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2724 char adevice[MAXDEVICENAME];
2725 NT_DEVICEMODE *nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE);
2727 if (nt_devmode == NULL) {
2728 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2729 return NULL;
2732 ZERO_STRUCTP(nt_devmode);
2734 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2735 fstrcpy(nt_devmode->devicename, adevice);
2737 fstrcpy(nt_devmode->formname, "Letter");
2739 nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
2740 nt_devmode->driverversion = 0x0400;
2741 nt_devmode->size = 0x00DC;
2742 nt_devmode->driverextra = 0x0000;
2743 nt_devmode->fields = DEVMODE_FORMNAME |
2744 DEVMODE_TTOPTION |
2745 DEVMODE_PRINTQUALITY |
2746 DEVMODE_DEFAULTSOURCE |
2747 DEVMODE_COPIES |
2748 DEVMODE_SCALE |
2749 DEVMODE_PAPERSIZE |
2750 DEVMODE_ORIENTATION;
2751 nt_devmode->orientation = DMORIENT_PORTRAIT;
2752 nt_devmode->papersize = DMPAPER_LETTER;
2753 nt_devmode->paperlength = 0;
2754 nt_devmode->paperwidth = 0;
2755 nt_devmode->scale = 0x64;
2756 nt_devmode->copies = 1;
2757 nt_devmode->defaultsource = DMBIN_FORMSOURCE;
2758 nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
2759 nt_devmode->color = DMRES_MONOCHROME;
2760 nt_devmode->duplex = DMDUP_SIMPLEX;
2761 nt_devmode->yresolution = 0;
2762 nt_devmode->ttoption = DMTT_SUBDEV;
2763 nt_devmode->collate = DMCOLLATE_FALSE;
2764 nt_devmode->icmmethod = 0;
2765 nt_devmode->icmintent = 0;
2766 nt_devmode->mediatype = 0;
2767 nt_devmode->dithertype = 0;
2769 /* non utilisés par un driver d'imprimante */
2770 nt_devmode->logpixels = 0;
2771 nt_devmode->bitsperpel = 0;
2772 nt_devmode->pelswidth = 0;
2773 nt_devmode->pelsheight = 0;
2774 nt_devmode->displayflags = 0;
2775 nt_devmode->displayfrequency = 0;
2776 nt_devmode->reserved1 = 0;
2777 nt_devmode->reserved2 = 0;
2778 nt_devmode->panningwidth = 0;
2779 nt_devmode->panningheight = 0;
2781 nt_devmode->nt_dev_private = NULL;
2782 return nt_devmode;
2785 /****************************************************************************
2786 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2787 ****************************************************************************/
2789 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2791 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2793 if(nt_devmode == NULL)
2794 return;
2796 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2798 SAFE_FREE(nt_devmode->nt_dev_private);
2799 SAFE_FREE(*devmode_ptr);
2802 /****************************************************************************
2803 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2804 ****************************************************************************/
2806 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2808 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2810 if ( !info )
2811 return;
2813 free_nt_devicemode(&info->devmode);
2815 TALLOC_FREE( *info_ptr );
2819 /****************************************************************************
2820 ****************************************************************************/
2821 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, const uint8 *buf, int buflen)
2823 int len = 0;
2824 int extra_len = 0;
2825 NT_DEVICEMODE devmode;
2827 ZERO_STRUCT(devmode);
2829 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2831 if (!*nt_devmode) return len;
2833 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2834 devmode.devicename,
2835 devmode.formname,
2837 &devmode.specversion,
2838 &devmode.driverversion,
2839 &devmode.size,
2840 &devmode.driverextra,
2841 &devmode.orientation,
2842 &devmode.papersize,
2843 &devmode.paperlength,
2844 &devmode.paperwidth,
2845 &devmode.scale,
2846 &devmode.copies,
2847 &devmode.defaultsource,
2848 &devmode.printquality,
2849 &devmode.color,
2850 &devmode.duplex,
2851 &devmode.yresolution,
2852 &devmode.ttoption,
2853 &devmode.collate,
2854 &devmode.logpixels,
2856 &devmode.fields,
2857 &devmode.bitsperpel,
2858 &devmode.pelswidth,
2859 &devmode.pelsheight,
2860 &devmode.displayflags,
2861 &devmode.displayfrequency,
2862 &devmode.icmmethod,
2863 &devmode.icmintent,
2864 &devmode.mediatype,
2865 &devmode.dithertype,
2866 &devmode.reserved1,
2867 &devmode.reserved2,
2868 &devmode.panningwidth,
2869 &devmode.panningheight,
2870 &devmode.nt_dev_private);
2872 if (devmode.nt_dev_private) {
2873 /* the len in tdb_unpack is an int value and
2874 * devmode.driverextra is only a short
2876 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
2877 devmode.driverextra=(uint16)extra_len;
2879 /* check to catch an invalid TDB entry so we don't segfault */
2880 if (devmode.driverextra == 0) {
2881 devmode.nt_dev_private = NULL;
2885 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2886 if (!*nt_devmode) {
2887 SAFE_FREE(devmode.nt_dev_private);
2888 return -1;
2891 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2892 if (devmode.nt_dev_private)
2893 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2895 return len;
2898 /****************************************************************************
2899 Allocate and initialize a new slot.
2900 ***************************************************************************/
2902 int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2904 NT_PRINTER_KEY *d;
2905 int key_index;
2907 if ( !name || !data )
2908 return -1;
2910 /* allocate another slot in the NT_PRINTER_KEY array */
2912 if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
2913 DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
2914 return -1;
2917 data->keys = d;
2919 key_index = data->num_keys;
2921 /* initialze new key */
2923 data->keys[key_index].name = talloc_strdup( data, name );
2925 if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
2926 return -1;
2928 data->num_keys++;
2930 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2932 return key_index;
2935 /****************************************************************************
2936 search for a registry key name in the existing printer data
2937 ***************************************************************************/
2939 int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
2941 int i;
2943 for ( i=0; i<data->num_keys; i++ ) {
2944 if ( strequal( data->keys[i].name, name ) ) {
2946 /* cleanup memory */
2948 TALLOC_FREE( data->keys[i].name );
2949 TALLOC_FREE( data->keys[i].values );
2951 /* if not the end of the array, move remaining elements down one slot */
2953 data->num_keys--;
2954 if ( data->num_keys && (i < data->num_keys) )
2955 memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
2957 break;
2962 return data->num_keys;
2965 /****************************************************************************
2966 search for a registry key name in the existing printer data
2967 ***************************************************************************/
2969 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2971 int key_index = -1;
2972 int i;
2974 if ( !data || !name )
2975 return -1;
2977 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2979 /* loop over all existing keys */
2981 for ( i=0; i<data->num_keys; i++ ) {
2982 if ( strequal(data->keys[i].name, name) ) {
2983 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2984 key_index = i;
2985 break;
2990 return key_index;
2993 /****************************************************************************
2994 ***************************************************************************/
2996 int get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2998 int i, j;
2999 int key_len;
3000 int num_subkeys = 0;
3001 char *p;
3002 fstring *subkeys_ptr = NULL;
3003 fstring subkeyname;
3005 *subkeys = NULL;
3007 if ( !data )
3008 return 0;
3010 if ( !key )
3011 return -1;
3013 /* special case of asking for the top level printer data registry key names */
3015 if ( strlen(key) == 0 ) {
3016 for ( i=0; i<data->num_keys; i++ ) {
3018 /* found a match, so allocate space and copy the name */
3020 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3021 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3022 num_subkeys+1));
3023 return -1;
3026 fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
3027 num_subkeys++;
3030 goto done;
3033 /* asking for the subkeys of some key */
3034 /* subkey paths are stored in the key name using '\' as the delimiter */
3036 for ( i=0; i<data->num_keys; i++ ) {
3037 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
3039 /* if we found the exact key, then break */
3040 key_len = strlen( key );
3041 if ( strlen(data->keys[i].name) == key_len )
3042 break;
3044 /* get subkey path */
3046 p = data->keys[i].name + key_len;
3047 if ( *p == '\\' )
3048 p++;
3049 fstrcpy( subkeyname, p );
3050 if ( (p = strchr( subkeyname, '\\' )) )
3051 *p = '\0';
3053 /* don't add a key more than once */
3055 for ( j=0; j<num_subkeys; j++ ) {
3056 if ( strequal( subkeys_ptr[j], subkeyname ) )
3057 break;
3060 if ( j != num_subkeys )
3061 continue;
3063 /* found a match, so allocate space and copy the name */
3065 if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
3066 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
3067 num_subkeys+1));
3068 return 0;
3071 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
3072 num_subkeys++;
3077 /* return error if the key was not found */
3079 if ( i == data->num_keys ) {
3080 SAFE_FREE(subkeys_ptr);
3081 return -1;
3084 done:
3085 /* tag off the end */
3087 if (num_subkeys)
3088 fstrcpy(subkeys_ptr[num_subkeys], "" );
3090 *subkeys = subkeys_ptr;
3092 return num_subkeys;
3095 #ifdef HAVE_ADS
3096 static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3097 const char *sz)
3099 regval_ctr_delvalue(ctr, val_name);
3100 regval_ctr_addvalue_sz(ctr, val_name, sz);
3103 static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
3104 uint32 dword)
3106 regval_ctr_delvalue(ctr, val_name);
3107 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
3108 (char *) &dword, sizeof(dword));
3111 static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
3112 bool b)
3114 uint8 bin_bool = (b ? 1 : 0);
3115 regval_ctr_delvalue(ctr, val_name);
3116 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
3117 (char *) &bin_bool, sizeof(bin_bool));
3120 static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
3121 const char *multi_sz)
3123 const char *a[2];
3125 a[0] = multi_sz;
3126 a[1] = NULL;
3128 regval_ctr_delvalue(ctr, val_name);
3129 regval_ctr_addvalue_multi_sz(ctr, val_name, a);
3132 /****************************************************************************
3133 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
3135 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
3136 * @return bool indicating success or failure
3137 ***************************************************************************/
3139 static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
3141 struct regval_ctr *ctr = NULL;
3142 fstring longname;
3143 const char *dnssuffix;
3144 char *allocated_string = NULL;
3145 const char *ascii_str;
3146 int i;
3148 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3149 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3150 ctr = info2->data->keys[i].values;
3152 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
3153 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
3155 /* we make the assumption that the netbios name is the same
3156 as the DNS name sinc ethe former will be what we used to
3157 join the domain */
3159 dnssuffix = get_mydnsdomname(talloc_tos());
3160 if (dnssuffix && *dnssuffix) {
3161 fstr_sprintf( longname, "%s.%s", global_myname(), dnssuffix );
3162 } else {
3163 fstrcpy( longname, global_myname() );
3166 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
3168 if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
3169 return false;
3171 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
3172 SAFE_FREE(allocated_string);
3174 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
3175 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
3176 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
3177 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
3178 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
3179 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
3180 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
3181 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
3182 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
3184 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
3185 (info2->attributes &
3186 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
3188 switch (info2->attributes & 0x3) {
3189 case 0:
3190 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
3191 break;
3192 case 1:
3193 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
3194 break;
3195 case 2:
3196 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
3197 break;
3198 default:
3199 ascii_str = "unknown";
3201 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
3203 return True;
3206 /*****************************************************************
3207 ****************************************************************/
3209 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
3210 struct GUID guid)
3212 int i;
3213 struct regval_ctr *ctr=NULL;
3215 /* find the DsSpooler key */
3216 if ((i = lookup_printerkey(info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
3217 i = add_new_printer_key(info2->data, SPOOL_DSSPOOLER_KEY);
3218 ctr = info2->data->keys[i].values;
3220 regval_ctr_delvalue(ctr, "objectGUID");
3222 /* We used to store this as a REG_BINARY but that causes
3223 Vista to whine */
3225 regval_ctr_addvalue_sz(ctr, "objectGUID",
3226 GUID_string(talloc_tos(), &guid));
3229 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
3230 NT_PRINTER_INFO_LEVEL *printer)
3232 ADS_STATUS ads_rc;
3233 LDAPMessage *res;
3234 char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
3235 char *srv_dn_utf8, **srv_cn_utf8;
3236 TALLOC_CTX *ctx;
3237 ADS_MODLIST mods;
3238 const char *attrs[] = {"objectGUID", NULL};
3239 struct GUID guid;
3240 WERROR win_rc = WERR_OK;
3241 size_t converted_size;
3243 /* build the ads mods */
3244 ctx = talloc_init("nt_printer_publish_ads");
3245 if (ctx == NULL) {
3246 return WERR_NOMEM;
3249 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
3251 /* figure out where to publish */
3252 ads_find_machine_acct(ads, &res, global_myname());
3254 /* We use ldap_get_dn here as we need the answer
3255 * in utf8 to call ldap_explode_dn(). JRA. */
3257 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
3258 if (!srv_dn_utf8) {
3259 TALLOC_FREE(ctx);
3260 return WERR_SERVER_UNAVAILABLE;
3262 ads_msgfree(ads, res);
3263 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
3264 if (!srv_cn_utf8) {
3265 TALLOC_FREE(ctx);
3266 ldap_memfree(srv_dn_utf8);
3267 return WERR_SERVER_UNAVAILABLE;
3269 /* Now convert to CH_UNIX. */
3270 if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
3271 TALLOC_FREE(ctx);
3272 ldap_memfree(srv_dn_utf8);
3273 ldap_memfree(srv_cn_utf8);
3274 return WERR_SERVER_UNAVAILABLE;
3276 if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
3277 TALLOC_FREE(ctx);
3278 ldap_memfree(srv_dn_utf8);
3279 ldap_memfree(srv_cn_utf8);
3280 TALLOC_FREE(srv_dn);
3281 return WERR_SERVER_UNAVAILABLE;
3284 ldap_memfree(srv_dn_utf8);
3285 ldap_memfree(srv_cn_utf8);
3287 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
3288 if (!srv_cn_escaped) {
3289 TALLOC_FREE(ctx);
3290 return WERR_SERVER_UNAVAILABLE;
3292 sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
3293 if (!sharename_escaped) {
3294 SAFE_FREE(srv_cn_escaped);
3295 TALLOC_FREE(ctx);
3296 return WERR_SERVER_UNAVAILABLE;
3299 prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
3301 SAFE_FREE(srv_cn_escaped);
3302 SAFE_FREE(sharename_escaped);
3304 mods = ads_init_mods(ctx);
3306 if (mods == NULL) {
3307 SAFE_FREE(prt_dn);
3308 TALLOC_FREE(ctx);
3309 return WERR_NOMEM;
3312 get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
3313 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
3314 printer->info_2->sharename);
3316 /* publish it */
3317 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
3318 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
3319 int i;
3320 for (i=0; mods[i] != 0; i++)
3322 mods[i] = (LDAPMod *)-1;
3323 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
3326 if (!ADS_ERR_OK(ads_rc))
3327 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
3329 /* retreive the guid and store it locally */
3330 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
3331 ZERO_STRUCT(guid);
3332 ads_pull_guid(ads, res, &guid);
3333 ads_msgfree(ads, res);
3334 store_printer_guid(printer->info_2, guid);
3335 win_rc = mod_a_printer(printer, 2);
3337 TALLOC_FREE(ctx);
3339 return win_rc;
3342 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
3343 NT_PRINTER_INFO_LEVEL *printer)
3345 ADS_STATUS ads_rc;
3346 LDAPMessage *res = NULL;
3347 char *prt_dn = NULL;
3349 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
3351 /* remove the printer from the directory */
3352 ads_rc = ads_find_printer_on_server(ads, &res,
3353 printer->info_2->sharename, global_myname());
3355 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
3356 prt_dn = ads_get_dn(ads, talloc_tos(), res);
3357 if (!prt_dn) {
3358 ads_msgfree(ads, res);
3359 return WERR_NOMEM;
3361 ads_rc = ads_del_dn(ads, prt_dn);
3362 TALLOC_FREE(prt_dn);
3365 if (res) {
3366 ads_msgfree(ads, res);
3368 return WERR_OK;
3371 /****************************************************************************
3372 * Publish a printer in the directory
3374 * @param snum describing printer service
3375 * @return WERROR indicating status of publishing
3376 ***************************************************************************/
3378 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3380 ADS_STATUS ads_rc;
3381 ADS_STRUCT *ads = NULL;
3382 NT_PRINTER_INFO_LEVEL *printer = NULL;
3383 WERROR win_rc;
3385 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3386 if (!W_ERROR_IS_OK(win_rc))
3387 goto done;
3389 switch (action) {
3390 case DSPRINT_PUBLISH:
3391 case DSPRINT_UPDATE:
3392 /* set the DsSpooler info and attributes */
3393 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
3394 win_rc = WERR_NOMEM;
3395 goto done;
3398 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
3399 break;
3400 case DSPRINT_UNPUBLISH:
3401 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
3402 break;
3403 default:
3404 win_rc = WERR_NOT_SUPPORTED;
3405 goto done;
3408 win_rc = mod_a_printer(printer, 2);
3409 if (!W_ERROR_IS_OK(win_rc)) {
3410 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
3411 goto done;
3414 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3415 if (!ads) {
3416 DEBUG(3, ("ads_init() failed\n"));
3417 win_rc = WERR_SERVER_UNAVAILABLE;
3418 goto done;
3420 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3421 SAFE_FREE(ads->auth.password);
3422 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3423 NULL, NULL);
3425 /* ads_connect() will find the DC for us */
3426 ads_rc = ads_connect(ads);
3427 if (!ADS_ERR_OK(ads_rc)) {
3428 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3429 win_rc = WERR_ACCESS_DENIED;
3430 goto done;
3433 switch (action) {
3434 case DSPRINT_PUBLISH:
3435 case DSPRINT_UPDATE:
3436 win_rc = nt_printer_publish_ads(ads, printer);
3437 break;
3438 case DSPRINT_UNPUBLISH:
3439 win_rc = nt_printer_unpublish_ads(ads, printer);
3440 break;
3443 done:
3444 free_a_printer(&printer, 2);
3445 ads_destroy(&ads);
3446 return win_rc;
3449 WERROR check_published_printers(void)
3451 ADS_STATUS ads_rc;
3452 ADS_STRUCT *ads = NULL;
3453 int snum;
3454 int n_services = lp_numservices();
3455 NT_PRINTER_INFO_LEVEL *printer = NULL;
3457 ads = ads_init(lp_realm(), lp_workgroup(), NULL);
3458 if (!ads) {
3459 DEBUG(3, ("ads_init() failed\n"));
3460 return WERR_SERVER_UNAVAILABLE;
3462 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
3463 SAFE_FREE(ads->auth.password);
3464 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
3465 NULL, NULL);
3467 /* ads_connect() will find the DC for us */
3468 ads_rc = ads_connect(ads);
3469 if (!ADS_ERR_OK(ads_rc)) {
3470 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
3471 ads_destroy(&ads);
3472 ads_kdestroy("MEMORY:prtpub_cache");
3473 return WERR_ACCESS_DENIED;
3476 for (snum = 0; snum < n_services; snum++) {
3477 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
3478 continue;
3480 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
3481 lp_servicename(snum))) &&
3482 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
3483 nt_printer_publish_ads(ads, printer);
3485 free_a_printer(&printer, 2);
3488 ads_destroy(&ads);
3489 ads_kdestroy("MEMORY:prtpub_cache");
3490 return WERR_OK;
3493 bool is_printer_published(Printer_entry *print_hnd, int snum,
3494 struct GUID *guid)
3496 NT_PRINTER_INFO_LEVEL *printer = NULL;
3497 struct regval_ctr *ctr;
3498 struct regval_blob *guid_val;
3499 WERROR win_rc;
3500 int i;
3501 bool ret = False;
3502 DATA_BLOB blob;
3504 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
3506 if (!W_ERROR_IS_OK(win_rc) ||
3507 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
3508 ((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
3509 !(ctr = printer->info_2->data->keys[i].values) ||
3510 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
3512 free_a_printer(&printer, 2);
3513 return False;
3516 /* fetching printer guids really ought to be a separate function. */
3518 if ( guid ) {
3519 char *guid_str;
3521 /* We used to store the guid as REG_BINARY, then swapped
3522 to REG_SZ for Vista compatibility so check for both */
3524 switch ( regval_type(guid_val) ){
3525 case REG_SZ:
3526 blob = data_blob_const(regval_data_p(guid_val),
3527 regval_size(guid_val));
3528 pull_reg_sz(talloc_tos(), NULL, &blob, (const char **)&guid_str);
3529 ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
3530 talloc_free(guid_str);
3531 break;
3532 case REG_BINARY:
3533 if ( regval_size(guid_val) != sizeof(struct GUID) ) {
3534 ret = False;
3535 break;
3537 memcpy(guid, regval_data_p(guid_val), sizeof(struct GUID));
3538 break;
3539 default:
3540 DEBUG(0,("is_printer_published: GUID value stored as "
3541 "invaluid type (%d)\n", regval_type(guid_val) ));
3542 break;
3546 free_a_printer(&printer, 2);
3547 return ret;
3549 #else
3550 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
3552 return WERR_OK;
3555 WERROR check_published_printers(void)
3557 return WERR_OK;
3560 bool is_printer_published(Printer_entry *print_hnd, int snum,
3561 struct GUID *guid)
3563 return False;
3565 #endif /* HAVE_ADS */
3567 /****************************************************************************
3568 ***************************************************************************/
3570 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
3572 NT_PRINTER_DATA *data;
3573 int i;
3574 int removed_keys = 0;
3575 int empty_slot;
3577 data = p2->data;
3578 empty_slot = data->num_keys;
3580 if ( !key )
3581 return WERR_INVALID_PARAM;
3583 /* remove all keys */
3585 if ( !strlen(key) ) {
3587 TALLOC_FREE( data );
3589 p2->data = NULL;
3591 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
3592 p2->printername ));
3594 return WERR_OK;
3597 /* remove a specific key (and all subkeys) */
3599 for ( i=0; i<data->num_keys; i++ ) {
3600 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
3601 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
3602 data->keys[i].name));
3604 TALLOC_FREE( data->keys[i].name );
3605 TALLOC_FREE( data->keys[i].values );
3607 /* mark the slot as empty */
3609 ZERO_STRUCTP( &data->keys[i] );
3613 /* find the first empty slot */
3615 for ( i=0; i<data->num_keys; i++ ) {
3616 if ( !data->keys[i].name ) {
3617 empty_slot = i;
3618 removed_keys++;
3619 break;
3623 if ( i == data->num_keys )
3624 /* nothing was removed */
3625 return WERR_INVALID_PARAM;
3627 /* move everything down */
3629 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
3630 if ( data->keys[i].name ) {
3631 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
3632 ZERO_STRUCTP( &data->keys[i] );
3633 empty_slot++;
3634 removed_keys++;
3638 /* update count */
3640 data->num_keys -= removed_keys;
3642 /* sanity check to see if anything is left */
3644 if ( !data->num_keys ) {
3645 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3647 SAFE_FREE( data->keys );
3648 ZERO_STRUCTP( data );
3651 return WERR_OK;
3654 /****************************************************************************
3655 ***************************************************************************/
3657 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3659 WERROR result = WERR_OK;
3660 int key_index;
3662 /* we must have names on non-zero length */
3664 if ( !key || !*key|| !value || !*value )
3665 return WERR_INVALID_NAME;
3667 /* find the printer key first */
3669 key_index = lookup_printerkey( p2->data, key );
3670 if ( key_index == -1 )
3671 return WERR_OK;
3673 /* make sure the value exists so we can return the correct error code */
3675 if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
3676 return WERR_BADFILE;
3678 regval_ctr_delvalue( p2->data->keys[key_index].values, value );
3680 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3681 key, value ));
3683 return result;
3686 /****************************************************************************
3687 ***************************************************************************/
3689 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3690 uint32 type, uint8 *data, int real_len )
3692 WERROR result = WERR_OK;
3693 int key_index;
3695 /* we must have names on non-zero length */
3697 if ( !key || !*key|| !value || !*value )
3698 return WERR_INVALID_NAME;
3700 /* find the printer key first */
3702 key_index = lookup_printerkey( p2->data, key );
3703 if ( key_index == -1 )
3704 key_index = add_new_printer_key( p2->data, key );
3706 if ( key_index == -1 )
3707 return WERR_NOMEM;
3709 regval_ctr_addvalue( p2->data->keys[key_index].values, value,
3710 type, (const char *)data, real_len );
3712 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3713 key, value, type, real_len ));
3715 return result;
3718 /****************************************************************************
3719 ***************************************************************************/
3721 struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3723 int key_index;
3725 if ( (key_index = lookup_printerkey( p2->data, key )) == -1 )
3726 return NULL;
3728 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3729 key, value ));
3731 return regval_ctr_getvalue( p2->data->keys[key_index].values, value );
3734 /****************************************************************************
3735 Unpack a list of registry values frem the TDB
3736 ***************************************************************************/
3738 static int unpack_values(NT_PRINTER_DATA *printer_data, const uint8 *buf, int buflen)
3740 int len = 0;
3741 uint32 type;
3742 fstring string;
3743 const char *valuename = NULL;
3744 const char *keyname = NULL;
3745 char *str;
3746 int size;
3747 uint8 *data_p;
3748 struct regval_blob *regval_p;
3749 int key_index;
3751 /* add the "PrinterDriverData" key first for performance reasons */
3753 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3755 /* loop and unpack the rest of the registry values */
3757 while ( True ) {
3759 /* check to see if there are any more registry values */
3761 regval_p = NULL;
3762 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3763 if ( !regval_p )
3764 break;
3766 /* unpack the next regval */
3768 len += tdb_unpack(buf+len, buflen-len, "fdB",
3769 string,
3770 &type,
3771 &size,
3772 &data_p);
3774 /* lookup for subkey names which have a type of REG_NONE */
3775 /* there's no data with this entry */
3777 if ( type == REG_NONE ) {
3778 if ( (key_index=lookup_printerkey( printer_data, string)) == -1 )
3779 add_new_printer_key( printer_data, string );
3780 continue;
3784 * break of the keyname from the value name.
3785 * Valuenames can have embedded '\'s so be careful.
3786 * only support one level of keys. See the
3787 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3788 * -- jerry
3791 str = strchr_m( string, '\\');
3793 /* Put in "PrinterDriverData" is no key specified */
3795 if ( !str ) {
3796 keyname = SPOOL_PRINTERDATA_KEY;
3797 valuename = string;
3799 else {
3800 *str = '\0';
3801 keyname = string;
3802 valuename = str+1;
3805 /* see if we need a new key */
3807 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3808 key_index = add_new_printer_key( printer_data, keyname );
3810 if ( key_index == -1 ) {
3811 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3812 keyname));
3813 break;
3816 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3818 /* Vista doesn't like unknown REG_BINARY values in DsSpooler.
3819 Thanks to Martin Zielinski for the hint. */
3821 if ( type == REG_BINARY &&
3822 strequal( keyname, SPOOL_DSSPOOLER_KEY ) &&
3823 strequal( valuename, "objectGUID" ) )
3825 struct GUID guid;
3827 /* convert the GUID to a UNICODE string */
3829 memcpy( &guid, data_p, sizeof(struct GUID) );
3831 regval_ctr_addvalue_sz(printer_data->keys[key_index].values,
3832 valuename,
3833 GUID_string(talloc_tos(), &guid));
3835 } else {
3836 /* add the value */
3838 regval_ctr_addvalue( printer_data->keys[key_index].values,
3839 valuename, type, (const char *)data_p,
3840 size );
3843 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3847 return len;
3850 /****************************************************************************
3851 ***************************************************************************/
3853 static char *last_from;
3854 static char *last_to;
3856 static const char *get_last_from(void)
3858 if (!last_from) {
3859 return "";
3861 return last_from;
3864 static const char *get_last_to(void)
3866 if (!last_to) {
3867 return "";
3869 return last_to;
3872 static bool set_last_from_to(const char *from, const char *to)
3874 char *orig_from = last_from;
3875 char *orig_to = last_to;
3877 last_from = SMB_STRDUP(from);
3878 last_to = SMB_STRDUP(to);
3880 SAFE_FREE(orig_from);
3881 SAFE_FREE(orig_to);
3883 if (!last_from || !last_to) {
3884 SAFE_FREE(last_from);
3885 SAFE_FREE(last_to);
3886 return false;
3888 return true;
3891 static void map_to_os2_driver(fstring drivername)
3893 char *mapfile = lp_os2_driver_map();
3894 char **lines = NULL;
3895 int numlines = 0;
3896 int i;
3898 if (!strlen(drivername))
3899 return;
3901 if (!*mapfile)
3902 return;
3904 if (strequal(drivername,get_last_from())) {
3905 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",
3906 drivername,get_last_to()));
3907 fstrcpy(drivername,get_last_to());
3908 return;
3911 lines = file_lines_load(mapfile, &numlines,0,NULL);
3912 if (numlines == 0 || lines == NULL) {
3913 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3914 TALLOC_FREE(lines);
3915 return;
3918 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3920 for( i = 0; i < numlines; i++) {
3921 char *nt_name = lines[i];
3922 char *os2_name = strchr(nt_name,'=');
3924 if (!os2_name)
3925 continue;
3927 *os2_name++ = 0;
3929 while (isspace(*nt_name))
3930 nt_name++;
3932 if (!*nt_name || strchr("#;",*nt_name))
3933 continue;
3936 int l = strlen(nt_name);
3937 while (l && isspace(nt_name[l-1])) {
3938 nt_name[l-1] = 0;
3939 l--;
3943 while (isspace(*os2_name))
3944 os2_name++;
3947 int l = strlen(os2_name);
3948 while (l && isspace(os2_name[l-1])) {
3949 os2_name[l-1] = 0;
3950 l--;
3954 if (strequal(nt_name,drivername)) {
3955 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3956 set_last_from_to(drivername,os2_name);
3957 fstrcpy(drivername,os2_name);
3958 TALLOC_FREE(lines);
3959 return;
3963 TALLOC_FREE(lines);
3966 /****************************************************************************
3967 Get a default printer info 2 struct.
3968 ****************************************************************************/
3970 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
3971 const char *servername,
3972 const char* sharename,
3973 bool get_loc_com)
3975 int snum = lp_servicenumber(sharename);
3977 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
3978 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
3979 servername, sharename);
3980 fstrcpy(info->sharename, sharename);
3981 fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
3983 /* by setting the driver name to an empty string, a local NT admin
3984 can now run the **local** APW to install a local printer driver
3985 for a Samba shared printer in 2.2. Without this, drivers **must** be
3986 installed on the Samba server for NT clients --jerry */
3987 #if 0 /* JERRY --do not uncomment-- */
3988 if (!*info->drivername)
3989 fstrcpy(info->drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3990 #endif
3993 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info->drivername));
3995 strlcpy(info->comment, "", sizeof(info->comment));
3996 fstrcpy(info->printprocessor, "winprint");
3997 fstrcpy(info->datatype, "RAW");
3999 #ifdef HAVE_CUPS
4000 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4001 /* Pull the location and comment strings from cups if we don't
4002 already have one */
4003 if ( !strlen(info->location) || !strlen(info->comment) ) {
4004 char *comment = NULL;
4005 char *location = NULL;
4006 if (cups_pull_comment_location(info, info->sharename,
4007 &comment, &location)) {
4008 strlcpy(info->comment, comment, sizeof(info->comment));
4009 fstrcpy(info->location, location);
4010 TALLOC_FREE(comment);
4011 TALLOC_FREE(location);
4015 #endif
4017 info->attributes = PRINTER_ATTRIBUTE_SAMBA;
4019 info->starttime = 0; /* Minutes since 12:00am GMT */
4020 info->untiltime = 0; /* Minutes since 12:00am GMT */
4021 info->priority = 1;
4022 info->default_priority = 1;
4023 info->setuptime = (uint32)time(NULL);
4026 * I changed this as I think it is better to have a generic
4027 * DEVMODE than to crash Win2k explorer.exe --jerry
4028 * See the HP Deskjet 990c Win2k drivers for an example.
4030 * However the default devmode appears to cause problems
4031 * with the HP CLJ 8500 PCL driver. Hence the addition of
4032 * the "default devmode" parameter --jerry 22/01/2002
4035 if (lp_default_devmode(snum)) {
4036 if ((info->devmode = construct_nt_devicemode(info->printername)) == NULL) {
4037 goto fail;
4039 } else {
4040 info->devmode = NULL;
4043 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4044 goto fail;
4047 info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
4048 if (!info->data) {
4049 goto fail;
4052 add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
4054 return WERR_OK;
4056 fail:
4057 if (info->devmode)
4058 free_nt_devicemode(&info->devmode);
4060 return WERR_ACCESS_DENIED;
4063 /****************************************************************************
4064 ****************************************************************************/
4066 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info,
4067 const char *servername,
4068 const char *sharename,
4069 bool get_loc_com)
4071 int len = 0;
4072 int snum = lp_servicenumber(sharename);
4073 TDB_DATA kbuf, dbuf;
4074 fstring printername;
4075 char adevice[MAXDEVICENAME];
4076 char *comment = NULL;
4078 kbuf = make_printer_tdbkey(talloc_tos(), sharename);
4080 dbuf = tdb_fetch(tdb_printers, kbuf);
4081 if (!dbuf.dptr) {
4082 return get_a_printer_2_default(info, servername,
4083 sharename, get_loc_com);
4086 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
4087 &info->attributes,
4088 &info->priority,
4089 &info->default_priority,
4090 &info->starttime,
4091 &info->untiltime,
4092 &info->status,
4093 &info->cjobs,
4094 &info->averageppm,
4095 &info->changeid,
4096 &info->c_setprinter,
4097 &info->setuptime,
4098 info->servername,
4099 info->printername,
4100 info->sharename,
4101 info->portname,
4102 info->drivername,
4103 &comment,
4104 info->location,
4105 info->sepfile,
4106 info->printprocessor,
4107 info->datatype,
4108 info->parameters);
4110 if (comment) {
4111 strlcpy(info->comment, comment, sizeof(info->comment));
4112 SAFE_FREE(comment);
4115 /* Samba has to have shared raw drivers. */
4116 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
4117 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
4119 /* Restore the stripped strings. */
4120 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
4122 if ( lp_force_printername(snum) ) {
4123 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
4124 } else {
4125 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info->printername);
4128 fstrcpy(info->printername, printername);
4130 #ifdef HAVE_CUPS
4131 if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
4132 /* Pull the location and comment strings from cups if we don't
4133 already have one */
4134 if ( !strlen(info->location) || !strlen(info->comment) ) {
4135 char *location = NULL;
4136 comment = NULL;
4137 if (cups_pull_comment_location(info, info->sharename,
4138 &comment, &location)) {
4139 strlcpy(info->comment, comment, sizeof(info->comment));
4140 fstrcpy(info->location, location);
4141 TALLOC_FREE(comment);
4142 TALLOC_FREE(location);
4146 #endif
4148 len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
4151 * Some client drivers freak out if there is a NULL devmode
4152 * (probably the driver is not checking before accessing
4153 * the devmode pointer) --jerry
4155 * See comments in get_a_printer_2_default()
4158 if (lp_default_devmode(snum) && !info->devmode) {
4159 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
4160 printername));
4161 info->devmode = construct_nt_devicemode(printername);
4164 slprintf( adevice, sizeof(adevice), "%s", info->printername );
4165 if (info->devmode) {
4166 fstrcpy(info->devmode->devicename, adevice);
4169 if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
4170 DEBUG(0,("unpack_values: talloc() failed!\n"));
4171 SAFE_FREE(dbuf.dptr);
4172 return WERR_NOMEM;
4174 len += unpack_values( info->data, dbuf.dptr+len, dbuf.dsize-len );
4176 /* This will get the current RPC talloc context, but we should be
4177 passing this as a parameter... fixme... JRA ! */
4179 if (!nt_printing_getsec(info, sharename, &info->secdesc_buf)) {
4180 SAFE_FREE(dbuf.dptr);
4181 return WERR_NOMEM;
4184 /* Fix for OS/2 drivers. */
4186 if (get_remote_arch() == RA_OS2) {
4187 map_to_os2_driver(info->drivername);
4190 SAFE_FREE(dbuf.dptr);
4192 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
4193 sharename, info->printername, info->drivername));
4195 return WERR_OK;
4198 /****************************************************************************
4199 Debugging function, dump at level 6 the struct in the logs.
4200 ****************************************************************************/
4201 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4203 uint32 result;
4204 NT_PRINTER_INFO_LEVEL_2 *info2;
4206 DEBUG(106,("Dumping printer at level [%d]\n", level));
4208 switch (level) {
4209 case 2:
4211 if (printer->info_2 == NULL)
4212 result=5;
4213 else
4215 info2=printer->info_2;
4217 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
4218 DEBUGADD(106,("priority:[%d]\n", info2->priority));
4219 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
4220 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
4221 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
4222 DEBUGADD(106,("status:[%d]\n", info2->status));
4223 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
4224 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
4225 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
4226 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
4227 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
4229 DEBUGADD(106,("servername:[%s]\n", info2->servername));
4230 DEBUGADD(106,("printername:[%s]\n", info2->printername));
4231 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
4232 DEBUGADD(106,("portname:[%s]\n", info2->portname));
4233 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
4234 DEBUGADD(106,("comment:[%s]\n", info2->comment));
4235 DEBUGADD(106,("location:[%s]\n", info2->location));
4236 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
4237 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
4238 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
4239 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
4240 result=0;
4242 break;
4244 default:
4245 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
4246 result=1;
4247 break;
4250 return result;
4253 /****************************************************************************
4254 Update the changeid time.
4255 This is SO NASTY as some drivers need this to change, others need it
4256 static. This value will change every second, and I must hope that this
4257 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
4258 UTAH ! JRA.
4259 ****************************************************************************/
4261 static uint32 rev_changeid(void)
4263 struct timeval tv;
4265 get_process_uptime(&tv);
4267 #if 1 /* JERRY */
4268 /* Return changeid as msec since spooler restart */
4269 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
4270 #else
4272 * This setting seems to work well but is too untested
4273 * to replace the above calculation. Left in for experiementation
4274 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
4276 return tv.tv_sec * 10 + tv.tv_usec / 100000;
4277 #endif
4282 * The function below are the high level ones.
4283 * only those ones must be called from the spoolss code.
4284 * JFM.
4287 /****************************************************************************
4288 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
4289 ****************************************************************************/
4291 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4293 WERROR result;
4295 dump_a_printer(printer, level);
4297 switch (level) {
4298 case 2:
4301 * Update the changestamp. Emperical tests show that the
4302 * ChangeID is always updated,but c_setprinter is
4303 * global spooler variable (not per printer).
4306 /* ChangeID **must** be increasing over the lifetime
4307 of client's spoolss service in order for the
4308 client's cache to show updates */
4310 printer->info_2->changeid = rev_changeid();
4313 * Because one day someone will ask:
4314 * NT->NT An admin connection to a remote
4315 * printer show changes imeediately in
4316 * the properities dialog
4318 * A non-admin connection will only show the
4319 * changes after viewing the properites page
4320 * 2 times. Seems to be related to a
4321 * race condition in the client between the spooler
4322 * updating the local cache and the Explorer.exe GUI
4323 * actually displaying the properties.
4325 * This is fixed in Win2k. admin/non-admin
4326 * connections both display changes immediately.
4328 * 14/12/01 --jerry
4331 result=update_a_printer_2(printer->info_2);
4332 break;
4334 default:
4335 result=WERR_UNKNOWN_LEVEL;
4336 break;
4339 return result;
4342 /****************************************************************************
4343 Initialize printer devmode & data with previously saved driver init values.
4344 ****************************************************************************/
4346 static bool set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
4348 int len = 0;
4349 char *key = NULL;
4350 TDB_DATA dbuf;
4351 NT_PRINTER_INFO_LEVEL_2 info;
4354 ZERO_STRUCT(info);
4357 * Delete any printer data 'values' already set. When called for driver
4358 * replace, there will generally be some, but during an add printer, there
4359 * should not be any (if there are delete them).
4362 if ( info_ptr->data )
4363 delete_all_printer_data( info_ptr, "" );
4365 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX,
4366 info_ptr->drivername) < 0) {
4367 return false;
4370 dbuf = tdb_fetch_bystring(tdb_drivers, key);
4371 if (!dbuf.dptr) {
4373 * When changing to a driver that has no init info in the tdb, remove
4374 * the previous drivers init info and leave the new on blank.
4376 free_nt_devicemode(&info_ptr->devmode);
4377 SAFE_FREE(key);
4378 return false;
4381 SAFE_FREE(key);
4383 * Get the saved DEVMODE..
4386 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
4389 * The saved DEVMODE contains the devicename from the printer used during
4390 * the initialization save. Change it to reflect the new printer.
4393 if ( info.devmode ) {
4394 ZERO_STRUCT(info.devmode->devicename);
4395 fstrcpy(info.devmode->devicename, info_ptr->printername);
4399 * NT/2k does not change out the entire DeviceMode of a printer
4400 * when changing the driver. Only the driverextra, private, &
4401 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
4403 * Later examination revealed that Windows NT/2k does reset the
4404 * the printer's device mode, bit **only** when you change a
4405 * property of the device mode such as the page orientation.
4406 * --jerry
4410 /* Bind the saved DEVMODE to the new the printer */
4412 free_nt_devicemode(&info_ptr->devmode);
4413 info_ptr->devmode = info.devmode;
4415 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
4416 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
4418 /* Add the printer data 'values' to the new printer */
4420 if ( !(info_ptr->data = TALLOC_ZERO_P( info_ptr, NT_PRINTER_DATA )) ) {
4421 DEBUG(0,("set_driver_init_2: talloc() failed!\n"));
4422 return False;
4425 len += unpack_values( info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
4427 SAFE_FREE(dbuf.dptr);
4429 return true;
4432 /****************************************************************************
4433 Initialize printer devmode & data with previously saved driver init values.
4434 When a printer is created using AddPrinter, the drivername bound to the
4435 printer is used to lookup previously saved driver initialization info, which
4436 is bound to the new printer.
4437 ****************************************************************************/
4439 bool set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4441 bool result = False;
4443 switch (level) {
4444 case 2:
4445 result = set_driver_init_2(printer->info_2);
4446 break;
4448 default:
4449 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
4450 level));
4451 break;
4454 return result;
4457 /****************************************************************************
4458 Delete driver init data stored for a specified driver
4459 ****************************************************************************/
4461 bool del_driver_init(const char *drivername)
4463 char *key;
4464 bool ret;
4466 if (!drivername || !*drivername) {
4467 DEBUG(3,("del_driver_init: No drivername specified!\n"));
4468 return false;
4471 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, drivername) < 0) {
4472 return false;
4475 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n",
4476 drivername));
4478 ret = (tdb_delete_bystring(tdb_drivers, key) == 0);
4479 SAFE_FREE(key);
4480 return ret;
4483 /****************************************************************************
4484 Pack up the DEVMODE and values for a printer into a 'driver init' entry
4485 in the tdb. Note: this is different from the driver entry and the printer
4486 entry. There should be a single driver init entry for each driver regardless
4487 of whether it was installed from NT or 2K. Technically, they should be
4488 different, but they work out to the same struct.
4489 ****************************************************************************/
4491 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
4493 char *key = NULL;
4494 uint8 *buf;
4495 int buflen, len, ret;
4496 int retlen;
4497 TDB_DATA dbuf;
4499 buf = NULL;
4500 buflen = 0;
4502 again:
4503 len = 0;
4504 len += pack_devicemode(info->devmode, buf+len, buflen-len);
4506 retlen = pack_values( info->data, buf+len, buflen-len );
4507 if (retlen == -1) {
4508 ret = -1;
4509 goto done;
4511 len += retlen;
4513 if (buflen < len) {
4514 buf = (uint8 *)SMB_REALLOC(buf, len);
4515 if (!buf) {
4516 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
4517 ret = -1;
4518 goto done;
4520 buflen = len;
4521 goto again;
4524 SAFE_FREE(key);
4525 if (asprintf(&key, "%s%s", DRIVER_INIT_PREFIX, info->drivername) < 0) {
4526 ret = (uint32)-1;
4527 goto done;
4530 dbuf.dptr = buf;
4531 dbuf.dsize = len;
4533 ret = tdb_store_bystring(tdb_drivers, key, dbuf, TDB_REPLACE);
4535 done:
4536 if (ret == -1)
4537 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
4539 SAFE_FREE(buf);
4541 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
4542 info->sharename, info->drivername));
4544 return ret;
4547 /****************************************************************************
4548 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
4549 ****************************************************************************/
4551 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
4553 uint32 result;
4555 dump_a_printer(printer, level);
4557 switch (level) {
4558 case 2:
4559 result = update_driver_init_2(printer->info_2);
4560 break;
4561 default:
4562 result = 1;
4563 break;
4566 return result;
4569 /****************************************************************************
4570 Convert the printer data value, a REG_BINARY array, into an initialization
4571 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
4572 got to keep the endians happy :).
4573 ****************************************************************************/
4575 static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
4576 const uint8_t *data, uint32_t data_len)
4578 struct spoolss_DeviceMode devmode;
4579 enum ndr_err_code ndr_err;
4580 DATA_BLOB blob;
4582 ZERO_STRUCT(devmode);
4584 blob = data_blob_const(data, data_len);
4586 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
4587 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
4588 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4589 DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
4590 return false;
4593 return convert_devicemode("", &devmode, &nt_devmode);
4596 /****************************************************************************
4597 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
4599 1. Use the driver's config DLL to this UNC printername and:
4600 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
4601 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
4602 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
4604 The last step triggers saving the "driver initialization" information for
4605 this printer into the tdb. Later, new printers that use this driver will
4606 have this initialization information bound to them. This simulates the
4607 driver initialization, as if it had run on the Samba server (as it would
4608 have done on NT).
4610 The Win32 client side code requirement sucks! But until we can run arbitrary
4611 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
4613 It would have been easier to use SetPrinter because all the UNMARSHALLING of
4614 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
4615 about it and you will realize why. JRR 010720
4616 ****************************************************************************/
4618 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
4620 WERROR status = WERR_OK;
4621 TALLOC_CTX *ctx = NULL;
4622 NT_DEVICEMODE *nt_devmode = NULL;
4623 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
4626 * When the DEVMODE is already set on the printer, don't try to unpack it.
4628 DEBUG(8,("save_driver_init_2: Enter...\n"));
4630 if ( !printer->info_2->devmode && data_len ) {
4632 * Set devmode on printer info, so entire printer initialization can be
4633 * saved to tdb.
4636 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
4637 return WERR_NOMEM;
4639 if ((nt_devmode = SMB_MALLOC_P(NT_DEVICEMODE)) == NULL) {
4640 status = WERR_NOMEM;
4641 goto done;
4644 ZERO_STRUCTP(nt_devmode);
4647 * The DEVMODE is held in the 'data' component of the param in raw binary.
4648 * Convert it to to a devmode structure
4650 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
4651 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
4652 status = WERR_INVALID_PARAM;
4653 goto done;
4656 printer->info_2->devmode = nt_devmode;
4660 * Pack up and add (or update) the DEVMODE and any current printer data to
4661 * a 'driver init' element in the tdb
4665 if ( update_driver_init(printer, 2) != 0 ) {
4666 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
4667 status = WERR_NOMEM;
4668 goto done;
4672 * If driver initialization info was successfully saved, set the current
4673 * printer to match it. This allows initialization of the current printer
4674 * as well as the driver.
4676 status = mod_a_printer(printer, 2);
4677 if (!W_ERROR_IS_OK(status)) {
4678 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
4679 printer->info_2->printername));
4682 done:
4683 talloc_destroy(ctx);
4684 free_nt_devicemode( &nt_devmode );
4686 printer->info_2->devmode = tmp_devmode;
4688 return status;
4691 /****************************************************************************
4692 Update the driver init info (DEVMODE and specifics) for a printer
4693 ****************************************************************************/
4695 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
4697 WERROR status = WERR_OK;
4699 switch (level) {
4700 case 2:
4701 status = save_driver_init_2( printer, data, data_len );
4702 break;
4703 default:
4704 status = WERR_UNKNOWN_LEVEL;
4705 break;
4708 return status;
4711 /****************************************************************************
4712 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4714 Previously the code had a memory allocation problem because it always
4715 used the TALLOC_CTX from the Printer_entry*. This context lasts
4716 as a long as the original handle is open. So if the client made a lot
4717 of getprinter[data]() calls, the memory usage would climb. Now we use
4718 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4719 still use the Printer_entry->ctx for maintaining the cache copy though
4720 since that object must live as long as the handle by definition.
4721 --jerry
4723 ****************************************************************************/
4725 static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4726 const char *sharename, bool get_loc_com)
4728 WERROR result;
4729 fstring servername;
4731 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4733 if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
4734 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4735 return WERR_NOMEM;
4738 switch (level) {
4739 case 2:
4740 if ( !((*pp_printer)->info_2 = TALLOC_ZERO_P(*pp_printer, NT_PRINTER_INFO_LEVEL_2)) ) {
4741 DEBUG(0,("get_a_printer: talloc() fail.\n"));
4742 TALLOC_FREE( *pp_printer );
4743 return WERR_NOMEM;
4746 if ( print_hnd )
4747 fstrcpy( servername, print_hnd->servername );
4748 else {
4749 fstrcpy( servername, "%L" );
4750 standard_sub_basic( "", "", servername,
4751 sizeof(servername)-1 );
4754 result = get_a_printer_2( (*pp_printer)->info_2,
4755 servername, sharename, get_loc_com);
4757 /* we have a new printer now. Save it with this handle */
4759 if ( !W_ERROR_IS_OK(result) ) {
4760 TALLOC_FREE( *pp_printer );
4761 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
4762 sharename, (unsigned int)level, win_errstr(result)));
4763 return result;
4766 dump_a_printer( *pp_printer, level);
4768 break;
4770 default:
4771 TALLOC_FREE( *pp_printer );
4772 return WERR_UNKNOWN_LEVEL;
4775 return WERR_OK;
4778 WERROR get_a_printer( Printer_entry *print_hnd,
4779 NT_PRINTER_INFO_LEVEL **pp_printer,
4780 uint32 level,
4781 const char *sharename)
4783 return get_a_printer_internal(print_hnd, pp_printer, level,
4784 sharename, true);
4787 WERROR get_a_printer_search( Printer_entry *print_hnd,
4788 NT_PRINTER_INFO_LEVEL **pp_printer,
4789 uint32 level,
4790 const char *sharename)
4792 return get_a_printer_internal(print_hnd, pp_printer, level,
4793 sharename, false);
4796 /****************************************************************************
4797 Deletes a NT_PRINTER_INFO_LEVEL struct.
4798 ****************************************************************************/
4800 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4802 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4804 if ( !printer )
4805 return 0;
4807 switch (level) {
4808 case 2:
4809 if ( printer->info_2 )
4810 free_nt_printer_info_level_2(&printer->info_2);
4811 break;
4813 default:
4814 DEBUG(0,("free_a_printer: unknown level! [%d]\n", level ));
4815 return 1;
4818 TALLOC_FREE(*pp_printer);
4820 return 0;
4823 /****************************************************************************
4824 ****************************************************************************/
4826 bool driver_info_ctr_to_info8(struct spoolss_AddDriverInfoCtr *r,
4827 struct spoolss_DriverInfo8 *_info8)
4829 struct spoolss_DriverInfo8 info8;
4831 ZERO_STRUCT(info8);
4833 switch (r->level) {
4834 case 3:
4835 info8.version = r->info.info3->version;
4836 info8.driver_name = r->info.info3->driver_name;
4837 info8.architecture = r->info.info3->architecture;
4838 info8.driver_path = r->info.info3->driver_path;
4839 info8.data_file = r->info.info3->data_file;
4840 info8.config_file = r->info.info3->config_file;
4841 info8.help_file = r->info.info3->help_file;
4842 info8.monitor_name = r->info.info3->monitor_name;
4843 info8.default_datatype = r->info.info3->default_datatype;
4844 if (r->info.info3->dependent_files && r->info.info3->dependent_files->string) {
4845 info8.dependent_files = r->info.info3->dependent_files->string;
4847 break;
4848 case 6:
4849 info8.version = r->info.info6->version;
4850 info8.driver_name = r->info.info6->driver_name;
4851 info8.architecture = r->info.info6->architecture;
4852 info8.driver_path = r->info.info6->driver_path;
4853 info8.data_file = r->info.info6->data_file;
4854 info8.config_file = r->info.info6->config_file;
4855 info8.help_file = r->info.info6->help_file;
4856 info8.monitor_name = r->info.info6->monitor_name;
4857 info8.default_datatype = r->info.info6->default_datatype;
4858 if (r->info.info6->dependent_files && r->info.info6->dependent_files->string) {
4859 info8.dependent_files = r->info.info6->dependent_files->string;
4861 info8.driver_date = r->info.info6->driver_date;
4862 info8.driver_version = r->info.info6->driver_version;
4863 info8.manufacturer_name = r->info.info6->manufacturer_name;
4864 info8.manufacturer_url = r->info.info6->manufacturer_url;
4865 info8.hardware_id = r->info.info6->hardware_id;
4866 info8.provider = r->info.info6->provider;
4867 break;
4868 case 8:
4869 info8.version = r->info.info8->version;
4870 info8.driver_name = r->info.info8->driver_name;
4871 info8.architecture = r->info.info8->architecture;
4872 info8.driver_path = r->info.info8->driver_path;
4873 info8.data_file = r->info.info8->data_file;
4874 info8.config_file = r->info.info8->config_file;
4875 info8.help_file = r->info.info8->help_file;
4876 info8.monitor_name = r->info.info8->monitor_name;
4877 info8.default_datatype = r->info.info8->default_datatype;
4878 if (r->info.info8->dependent_files && r->info.info8->dependent_files->string) {
4879 info8.dependent_files = r->info.info8->dependent_files->string;
4881 if (r->info.info8->previous_names && r->info.info8->previous_names->string) {
4882 info8.previous_names = r->info.info8->previous_names->string;
4884 info8.driver_date = r->info.info8->driver_date;
4885 info8.driver_version = r->info.info8->driver_version;
4886 info8.manufacturer_name = r->info.info8->manufacturer_name;
4887 info8.manufacturer_url = r->info.info8->manufacturer_url;
4888 info8.hardware_id = r->info.info8->hardware_id;
4889 info8.provider = r->info.info8->provider;
4890 info8.print_processor = r->info.info8->print_processor;
4891 info8.vendor_setup = r->info.info8->vendor_setup;
4892 if (r->info.info8->color_profiles && r->info.info8->color_profiles->string) {
4893 info8.color_profiles = r->info.info8->color_profiles->string;
4895 info8.inf_path = r->info.info8->inf_path;
4896 info8.printer_driver_attributes = r->info.info8->printer_driver_attributes;
4897 if (r->info.info8->core_driver_dependencies && r->info.info8->core_driver_dependencies->string) {
4898 info8.core_driver_dependencies = r->info.info8->core_driver_dependencies->string;
4900 info8.min_inbox_driver_ver_date = r->info.info8->min_inbox_driver_ver_date;
4901 info8.min_inbox_driver_ver_version = r->info.info8->min_inbox_driver_ver_version;
4902 break;
4903 default:
4904 return false;
4907 *_info8 = info8;
4909 return true;
4913 uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
4914 struct spoolss_AddDriverInfoCtr *r,
4915 char **driver_name,
4916 uint32_t *version)
4918 struct spoolss_DriverInfo8 info8;
4920 ZERO_STRUCT(info8);
4922 DEBUG(10,("adding a printer at level [%d]\n", r->level));
4924 if (!driver_info_ctr_to_info8(r, &info8)) {
4925 return -1;
4928 *driver_name = talloc_strdup(mem_ctx, info8.driver_name);
4929 if (!*driver_name) {
4930 return -1;
4932 *version = info8.version;
4934 return add_a_printer_driver_8(&info8);
4937 /****************************************************************************
4938 ****************************************************************************/
4940 WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
4941 struct spoolss_DriverInfo8 **driver,
4942 const char *drivername, const char *architecture,
4943 uint32_t version)
4945 WERROR result;
4946 struct spoolss_DriverInfo3 info3;
4947 struct spoolss_DriverInfo8 *info8;
4949 ZERO_STRUCT(info3);
4951 /* Sometime we just want any version of the driver */
4953 if (version == DRIVER_ANY_VERSION) {
4954 /* look for Win2k first and then for NT4 */
4955 result = get_a_printer_driver_3(mem_ctx,
4956 &info3,
4957 drivername,
4958 architecture, 3);
4959 if (!W_ERROR_IS_OK(result)) {
4960 result = get_a_printer_driver_3(mem_ctx,
4961 &info3,
4962 drivername,
4963 architecture, 2);
4965 } else {
4966 result = get_a_printer_driver_3(mem_ctx,
4967 &info3,
4968 drivername,
4969 architecture,
4970 version);
4973 if (!W_ERROR_IS_OK(result)) {
4974 return result;
4977 info8 = talloc_zero(mem_ctx, struct spoolss_DriverInfo8);
4978 if (!info8) {
4979 return WERR_NOMEM;
4982 info8->version = info3.version;
4983 info8->driver_name = info3.driver_name;
4984 info8->architecture = info3.architecture;
4985 info8->driver_path = info3.driver_path;
4986 info8->data_file = info3.data_file;
4987 info8->config_file = info3.config_file;
4988 info8->help_file = info3.help_file;
4989 info8->dependent_files = info3.dependent_files;
4990 info8->monitor_name = info3.monitor_name;
4991 info8->default_datatype = info3.default_datatype;
4993 *driver = info8;
4995 return WERR_OK;
4998 /****************************************************************************
4999 ****************************************************************************/
5001 uint32_t free_a_printer_driver(struct spoolss_DriverInfo8 *driver)
5003 talloc_free(driver);
5004 return 0;
5008 /****************************************************************************
5009 Determine whether or not a particular driver is currently assigned
5010 to a printer
5011 ****************************************************************************/
5013 bool printer_driver_in_use(const struct spoolss_DriverInfo8 *r)
5015 int snum;
5016 int n_services = lp_numservices();
5017 NT_PRINTER_INFO_LEVEL *printer = NULL;
5018 bool in_use = False;
5020 if (!r) {
5021 return false;
5024 DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
5026 /* loop through the printers.tdb and check for the drivername */
5028 for (snum=0; snum<n_services && !in_use; snum++) {
5029 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
5030 continue;
5032 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
5033 continue;
5035 if (strequal(r->driver_name, printer->info_2->drivername))
5036 in_use = True;
5038 free_a_printer( &printer, 2 );
5041 DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
5043 if ( in_use ) {
5044 struct spoolss_DriverInfo8 *d;
5045 WERROR werr;
5047 DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", r->driver_name));
5049 /* we can still remove the driver if there is one of
5050 "Windows NT x86" version 2 or 3 left */
5052 if (!strequal("Windows NT x86", r->architecture)) {
5053 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
5055 else {
5056 switch (r->version) {
5057 case 2:
5058 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 3);
5059 break;
5060 case 3:
5061 werr = get_a_printer_driver(talloc_tos(), &d, r->driver_name, "Windows NT x86", 2);
5062 break;
5063 default:
5064 DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
5065 r->version));
5066 werr = WERR_UNKNOWN_PRINTER_DRIVER;
5067 break;
5071 /* now check the error code */
5073 if ( W_ERROR_IS_OK(werr) ) {
5074 /* it's ok to remove the driver, we have other architctures left */
5075 in_use = False;
5076 free_a_printer_driver(d);
5080 /* report that the driver is not in use by default */
5082 return in_use;
5086 /**********************************************************************
5087 Check to see if a ogiven file is in use by *info
5088 *********************************************************************/
5090 static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo8 *info)
5092 int i = 0;
5094 if ( !info )
5095 return False;
5097 /* mz: skip files that are in the list but already deleted */
5098 if (!file || !file[0]) {
5099 return false;
5102 if (strequal(file, info->driver_path))
5103 return True;
5105 if (strequal(file, info->data_file))
5106 return True;
5108 if (strequal(file, info->config_file))
5109 return True;
5111 if (strequal(file, info->help_file))
5112 return True;
5114 /* see of there are any dependent files to examine */
5116 if (!info->dependent_files)
5117 return False;
5119 while (info->dependent_files[i] && *info->dependent_files[i]) {
5120 if (strequal(file, info->dependent_files[i]))
5121 return True;
5122 i++;
5125 return False;
5129 /**********************************************************************
5130 Utility function to remove the dependent file pointed to by the
5131 input parameter from the list
5132 *********************************************************************/
5134 static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
5137 /* bump everything down a slot */
5139 while (files && files[idx+1]) {
5140 files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
5141 idx++;
5144 files[idx] = NULL;
5146 return;
5149 /**********************************************************************
5150 Check if any of the files used by src are also used by drv
5151 *********************************************************************/
5153 static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
5154 struct spoolss_DriverInfo8 *src,
5155 const struct spoolss_DriverInfo8 *drv)
5157 bool in_use = False;
5158 int i = 0;
5160 if ( !src || !drv )
5161 return False;
5163 /* check each file. Remove it from the src structure if it overlaps */
5165 if (drv_file_in_use(src->driver_path, drv)) {
5166 in_use = True;
5167 DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
5168 src->driver_path = talloc_strdup(mem_ctx, "");
5169 if (!src->driver_path) { return false; }
5172 if (drv_file_in_use(src->data_file, drv)) {
5173 in_use = True;
5174 DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
5175 src->data_file = talloc_strdup(mem_ctx, "");
5176 if (!src->data_file) { return false; }
5179 if (drv_file_in_use(src->config_file, drv)) {
5180 in_use = True;
5181 DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
5182 src->config_file = talloc_strdup(mem_ctx, "");
5183 if (!src->config_file) { return false; }
5186 if (drv_file_in_use(src->help_file, drv)) {
5187 in_use = True;
5188 DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
5189 src->help_file = talloc_strdup(mem_ctx, "");
5190 if (!src->help_file) { return false; }
5193 /* are there any dependentfiles to examine? */
5195 if (!src->dependent_files)
5196 return in_use;
5198 while (src->dependent_files[i] && *src->dependent_files[i]) {
5199 if (drv_file_in_use(src->dependent_files[i], drv)) {
5200 in_use = True;
5201 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
5202 trim_dependent_file(mem_ctx, src->dependent_files, i);
5203 } else
5204 i++;
5207 return in_use;
5210 /****************************************************************************
5211 Determine whether or not a particular driver files are currently being
5212 used by any other driver.
5214 Return value is True if any files were in use by other drivers
5215 and False otherwise.
5217 Upon return, *info has been modified to only contain the driver files
5218 which are not in use
5220 Fix from mz:
5222 This needs to check all drivers to ensure that all files in use
5223 have been removed from *info, not just the ones in the first
5224 match.
5225 ****************************************************************************/
5227 bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
5228 struct spoolss_DriverInfo8 *info)
5230 int i;
5231 int ndrivers;
5232 uint32 version;
5233 fstring *list = NULL;
5234 struct spoolss_DriverInfo8 *driver;
5235 bool in_use = false;
5237 if ( !info )
5238 return False;
5240 version = info->version;
5242 /* loop over all driver versions */
5244 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
5246 /* get the list of drivers */
5248 list = NULL;
5249 ndrivers = get_ntdrivers(&list, info->architecture, version);
5251 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
5252 ndrivers, info->architecture, version));
5254 /* check each driver for overlap in files */
5256 for (i=0; i<ndrivers; i++) {
5257 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
5259 driver = NULL;
5261 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, list[i], info->architecture, version))) {
5262 SAFE_FREE(list);
5263 return True;
5266 /* check if d2 uses any files from d1 */
5267 /* only if this is a different driver than the one being deleted */
5269 if (!strequal(info->driver_name, driver->driver_name)) {
5270 if (trim_overlap_drv_files(mem_ctx, info, driver)) {
5271 /* mz: Do not instantly return -
5272 * we need to ensure this file isn't
5273 * also in use by other drivers. */
5274 in_use = true;
5278 free_a_printer_driver(driver);
5281 SAFE_FREE(list);
5283 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
5285 return in_use;
5288 static NTSTATUS driver_unlink_internals(connection_struct *conn,
5289 const char *name)
5291 struct smb_filename *smb_fname = NULL;
5292 NTSTATUS status;
5294 status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
5295 &smb_fname);
5296 if (!NT_STATUS_IS_OK(status)) {
5297 return status;
5300 status = unlink_internals(conn, NULL, 0, smb_fname, false);
5302 TALLOC_FREE(smb_fname);
5303 return status;
5306 /****************************************************************************
5307 Actually delete the driver files. Make sure that
5308 printer_driver_files_in_use() return False before calling
5309 this.
5310 ****************************************************************************/
5312 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
5313 const struct spoolss_DriverInfo8 *r)
5315 int i = 0;
5316 char *s;
5317 const char *file;
5318 connection_struct *conn;
5319 NTSTATUS nt_status;
5320 char *oldcwd;
5321 fstring printdollar;
5322 int printdollar_snum;
5323 bool ret = false;
5325 if (!r) {
5326 return false;
5329 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
5330 r->driver_name, r->version));
5332 fstrcpy(printdollar, "print$");
5334 printdollar_snum = find_service(printdollar);
5335 if (printdollar_snum == -1) {
5336 return false;
5339 nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
5340 lp_pathname(printdollar_snum),
5341 rpc_pipe->server_info, &oldcwd);
5342 if (!NT_STATUS_IS_OK(nt_status)) {
5343 DEBUG(0,("delete_driver_files: create_conn_struct "
5344 "returned %s\n", nt_errstr(nt_status)));
5345 return false;
5348 if ( !CAN_WRITE(conn) ) {
5349 DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
5350 goto fail;
5353 /* now delete the files; must strip the '\print$' string from
5354 fron of path */
5356 if (r->driver_path && r->driver_path[0]) {
5357 if ((s = strchr(&r->driver_path[1], '\\')) != NULL) {
5358 file = s;
5359 DEBUG(10,("deleting driverfile [%s]\n", s));
5360 driver_unlink_internals(conn, file);
5364 if (r->config_file && r->config_file[0]) {
5365 if ((s = strchr(&r->config_file[1], '\\')) != NULL) {
5366 file = s;
5367 DEBUG(10,("deleting configfile [%s]\n", s));
5368 driver_unlink_internals(conn, file);
5372 if (r->data_file && r->data_file[0]) {
5373 if ((s = strchr(&r->data_file[1], '\\')) != NULL) {
5374 file = s;
5375 DEBUG(10,("deleting datafile [%s]\n", s));
5376 driver_unlink_internals(conn, file);
5380 if (r->help_file && r->help_file[0]) {
5381 if ((s = strchr(&r->help_file[1], '\\')) != NULL) {
5382 file = s;
5383 DEBUG(10,("deleting helpfile [%s]\n", s));
5384 driver_unlink_internals(conn, file);
5388 /* check if we are done removing files */
5390 if (r->dependent_files) {
5391 while (r->dependent_files[i] && r->dependent_files[i][0]) {
5392 char *p;
5394 /* bypass the "\print$" portion of the path */
5396 if ((p = strchr(r->dependent_files[i]+1, '\\')) != NULL) {
5397 file = p;
5398 DEBUG(10,("deleting dependent file [%s]\n", file));
5399 driver_unlink_internals(conn, file);
5402 i++;
5406 goto done;
5407 fail:
5408 ret = false;
5409 done:
5410 if (conn != NULL) {
5411 vfs_ChDir(conn, oldcwd);
5412 conn_free(conn);
5414 return ret;
5417 /****************************************************************************
5418 Remove a printer driver from the TDB. This assumes that the the driver was
5419 previously looked up.
5420 ***************************************************************************/
5422 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
5423 const struct spoolss_DriverInfo8 *r,
5424 uint32 version, bool delete_files )
5426 char *key = NULL;
5427 const char *arch;
5428 TDB_DATA dbuf;
5430 /* delete the tdb data first */
5432 arch = get_short_archi(r->architecture);
5433 if (!arch) {
5434 return WERR_UNKNOWN_PRINTER_DRIVER;
5436 if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
5437 arch, version, r->driver_name) < 0) {
5438 return WERR_NOMEM;
5441 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
5442 key, delete_files ? "TRUE" : "FALSE" ));
5444 /* check if the driver actually exists for this environment */
5446 dbuf = tdb_fetch_bystring( tdb_drivers, key );
5447 if ( !dbuf.dptr ) {
5448 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
5449 SAFE_FREE(key);
5450 return WERR_UNKNOWN_PRINTER_DRIVER;
5453 SAFE_FREE( dbuf.dptr );
5455 /* ok... the driver exists so the delete should return success */
5457 if (tdb_delete_bystring(tdb_drivers, key) == -1) {
5458 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
5459 SAFE_FREE(key);
5460 return WERR_ACCESS_DENIED;
5464 * now delete any associated files if delete_files == True
5465 * even if this part failes, we return succes because the
5466 * driver doesn not exist any more
5469 if ( delete_files )
5470 delete_driver_files(rpc_pipe, r);
5472 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
5473 SAFE_FREE(key);
5475 return WERR_OK;
5478 /****************************************************************************
5479 Store a security desc for a printer.
5480 ****************************************************************************/
5482 WERROR nt_printing_setsec(const char *sharename, SEC_DESC_BUF *secdesc_ctr)
5484 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5485 SEC_DESC_BUF *old_secdesc_ctr = NULL;
5486 TALLOC_CTX *mem_ctx = NULL;
5487 TDB_DATA kbuf;
5488 TDB_DATA dbuf;
5489 DATA_BLOB blob;
5490 WERROR status;
5491 NTSTATUS nt_status;
5493 mem_ctx = talloc_init("nt_printing_setsec");
5494 if (mem_ctx == NULL)
5495 return WERR_NOMEM;
5497 /* The old owner and group sids of the security descriptor are not
5498 present when new ACEs are added or removed by changing printer
5499 permissions through NT. If they are NULL in the new security
5500 descriptor then copy them over from the old one. */
5502 if (!secdesc_ctr->sd->owner_sid || !secdesc_ctr->sd->group_sid) {
5503 DOM_SID *owner_sid, *group_sid;
5504 SEC_ACL *dacl, *sacl;
5505 SEC_DESC *psd = NULL;
5506 size_t size;
5508 if (!nt_printing_getsec(mem_ctx, sharename, &old_secdesc_ctr)) {
5509 status = WERR_NOMEM;
5510 goto out;
5513 /* Pick out correct owner and group sids */
5515 owner_sid = secdesc_ctr->sd->owner_sid ?
5516 secdesc_ctr->sd->owner_sid :
5517 old_secdesc_ctr->sd->owner_sid;
5519 group_sid = secdesc_ctr->sd->group_sid ?
5520 secdesc_ctr->sd->group_sid :
5521 old_secdesc_ctr->sd->group_sid;
5523 dacl = secdesc_ctr->sd->dacl ?
5524 secdesc_ctr->sd->dacl :
5525 old_secdesc_ctr->sd->dacl;
5527 sacl = secdesc_ctr->sd->sacl ?
5528 secdesc_ctr->sd->sacl :
5529 old_secdesc_ctr->sd->sacl;
5531 /* Make a deep copy of the security descriptor */
5533 psd = make_sec_desc(mem_ctx, secdesc_ctr->sd->revision, secdesc_ctr->sd->type,
5534 owner_sid, group_sid,
5535 sacl,
5536 dacl,
5537 &size);
5539 if (!psd) {
5540 status = WERR_NOMEM;
5541 goto out;
5544 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
5547 if (!new_secdesc_ctr) {
5548 new_secdesc_ctr = secdesc_ctr;
5551 /* Store the security descriptor in a tdb */
5553 nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
5554 &blob.data, &blob.length);
5555 if (!NT_STATUS_IS_OK(nt_status)) {
5556 status = ntstatus_to_werror(nt_status);
5557 goto out;
5560 kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
5562 dbuf.dptr = (unsigned char *)blob.data;
5563 dbuf.dsize = blob.length;
5565 if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
5566 status = WERR_OK;
5567 } else {
5568 DEBUG(1,("Failed to store secdesc for %s\n", sharename));
5569 status = WERR_BADFUNC;
5572 /* Free malloc'ed memory */
5573 talloc_free(blob.data);
5575 out:
5577 if (mem_ctx)
5578 talloc_destroy(mem_ctx);
5579 return status;
5582 /****************************************************************************
5583 Construct a default security descriptor buffer for a printer.
5584 ****************************************************************************/
5586 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
5588 SEC_ACE ace[5]; /* max number of ace entries */
5589 int i = 0;
5590 uint32_t sa;
5591 SEC_ACL *psa = NULL;
5592 SEC_DESC_BUF *sdb = NULL;
5593 SEC_DESC *psd = NULL;
5594 DOM_SID adm_sid;
5595 size_t sd_size;
5597 /* Create an ACE where Everyone is allowed to print */
5599 sa = PRINTER_ACE_PRINT;
5600 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
5601 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5603 /* Add the domain admins group if we are a DC */
5605 if ( IS_DC ) {
5606 DOM_SID domadmins_sid;
5608 sid_compose(&domadmins_sid, get_global_sam_sid(),
5609 DOMAIN_GROUP_RID_ADMINS);
5611 sa = PRINTER_ACE_FULL_CONTROL;
5612 init_sec_ace(&ace[i++], &domadmins_sid,
5613 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5614 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5615 init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5616 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5618 else if (secrets_fetch_domain_sid(lp_workgroup(), &adm_sid)) {
5619 sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
5621 sa = PRINTER_ACE_FULL_CONTROL;
5622 init_sec_ace(&ace[i++], &adm_sid,
5623 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5624 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5625 init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
5626 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5629 /* add BUILTIN\Administrators as FULL CONTROL */
5631 sa = PRINTER_ACE_FULL_CONTROL;
5632 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5633 SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
5634 SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
5635 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
5636 SEC_ACE_TYPE_ACCESS_ALLOWED,
5637 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
5639 /* Make the security descriptor owned by the BUILTIN\Administrators */
5641 /* The ACL revision number in rpc_secdesc.h differs from the one
5642 created by NT when setting ACE entries in printer
5643 descriptors. NT4 complains about the property being edited by a
5644 NT5 machine. */
5646 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
5647 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
5648 &global_sid_Builtin_Administrators,
5649 &global_sid_Builtin_Administrators,
5650 NULL, psa, &sd_size);
5653 if (!psd) {
5654 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
5655 return NULL;
5658 sdb = make_sec_desc_buf(ctx, sd_size, psd);
5660 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
5661 (unsigned int)sd_size));
5663 return sdb;
5666 /****************************************************************************
5667 Get a security desc for a printer.
5668 ****************************************************************************/
5670 bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
5672 TDB_DATA kbuf;
5673 TDB_DATA dbuf;
5674 DATA_BLOB blob;
5675 char *temp;
5676 NTSTATUS status;
5678 if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
5679 sharename = temp + 1;
5682 /* Fetch security descriptor from tdb */
5684 kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
5686 dbuf = tdb_fetch(tdb_printers, kbuf);
5687 if (dbuf.dptr) {
5689 status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
5690 secdesc_ctr);
5691 SAFE_FREE(dbuf.dptr);
5693 if (NT_STATUS_IS_OK(status)) {
5694 return true;
5698 *secdesc_ctr = construct_default_printer_sdb(ctx);
5699 if (!*secdesc_ctr) {
5700 return false;
5703 status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
5704 &blob.data, &blob.length);
5705 if (NT_STATUS_IS_OK(status)) {
5706 dbuf.dptr = (unsigned char *)blob.data;
5707 dbuf.dsize = blob.length;
5708 tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
5709 talloc_free(blob.data);
5712 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
5713 this security descriptor has been created when winbindd was
5714 down. Take ownership of security descriptor. */
5716 if (sid_equal((*secdesc_ctr)->sd->owner_sid, &global_sid_World)) {
5717 DOM_SID owner_sid;
5719 /* Change sd owner to workgroup administrator */
5721 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
5722 SEC_DESC_BUF *new_secdesc_ctr = NULL;
5723 SEC_DESC *psd = NULL;
5724 size_t size;
5726 /* Create new sd */
5728 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
5730 psd = make_sec_desc(ctx, (*secdesc_ctr)->sd->revision, (*secdesc_ctr)->sd->type,
5731 &owner_sid,
5732 (*secdesc_ctr)->sd->group_sid,
5733 (*secdesc_ctr)->sd->sacl,
5734 (*secdesc_ctr)->sd->dacl,
5735 &size);
5737 if (!psd) {
5738 return False;
5741 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
5742 if (!new_secdesc_ctr) {
5743 return False;
5746 /* Swap with other one */
5748 *secdesc_ctr = new_secdesc_ctr;
5750 /* Set it */
5752 nt_printing_setsec(sharename, *secdesc_ctr);
5756 if (DEBUGLEVEL >= 10) {
5757 SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
5758 int i;
5760 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5761 sharename, the_acl->num_aces));
5763 for (i = 0; i < the_acl->num_aces; i++) {
5764 DEBUG(10, ("%s %d %d 0x%08x\n",
5765 sid_string_dbg(&the_acl->aces[i].trustee),
5766 the_acl->aces[i].type, the_acl->aces[i].flags,
5767 the_acl->aces[i].access_mask));
5771 return True;
5774 /* error code:
5775 0: everything OK
5776 1: level not implemented
5777 2: file doesn't exist
5778 3: can't allocate memory
5779 4: can't free memory
5780 5: non existant struct
5784 A printer and a printer driver are 2 different things.
5785 NT manages them separatelly, Samba does the same.
5786 Why ? Simply because it's easier and it makes sense !
5788 Now explanation: You have 3 printers behind your samba server,
5789 2 of them are the same make and model (laser A and B). But laser B
5790 has an 3000 sheet feeder and laser A doesn't such an option.
5791 Your third printer is an old dot-matrix model for the accounting :-).
5793 If the /usr/local/samba/lib directory (default dir), you will have
5794 5 files to describe all of this.
5796 3 files for the printers (1 by printer):
5797 NTprinter_laser A
5798 NTprinter_laser B
5799 NTprinter_accounting
5800 2 files for the drivers (1 for the laser and 1 for the dot matrix)
5801 NTdriver_printer model X
5802 NTdriver_printer model Y
5804 jfm: I should use this comment for the text file to explain
5805 same thing for the forms BTW.
5806 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
5810 /* Convert generic access rights to printer object specific access rights.
5811 It turns out that NT4 security descriptors use generic access rights and
5812 NT5 the object specific ones. */
5814 void map_printer_permissions(SEC_DESC *sd)
5816 int i;
5818 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5819 se_map_generic(&sd->dacl->aces[i].access_mask,
5820 &printer_generic_mapping);
5824 void map_job_permissions(SEC_DESC *sd)
5826 int i;
5828 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
5829 se_map_generic(&sd->dacl->aces[i].access_mask,
5830 &job_generic_mapping);
5835 /****************************************************************************
5836 Check a user has permissions to perform the given operation. We use the
5837 permission constants defined in include/rpc_spoolss.h to check the various
5838 actions we perform when checking printer access.
5840 PRINTER_ACCESS_ADMINISTER:
5841 print_queue_pause, print_queue_resume, update_printer_sec,
5842 update_printer, spoolss_addprinterex_level_2,
5843 _spoolss_setprinterdata
5845 PRINTER_ACCESS_USE:
5846 print_job_start
5848 JOB_ACCESS_ADMINISTER:
5849 print_job_delete, print_job_pause, print_job_resume,
5850 print_queue_purge
5852 Try access control in the following order (for performance reasons):
5853 1) root and SE_PRINT_OPERATOR can do anything (easy check)
5854 2) check security descriptor (bit comparisons in memory)
5855 3) "printer admins" (may result in numerous calls to winbind)
5857 ****************************************************************************/
5858 bool print_access_check(struct auth_serversupplied_info *server_info, int snum,
5859 int access_type)
5861 SEC_DESC_BUF *secdesc = NULL;
5862 uint32 access_granted;
5863 NTSTATUS status;
5864 const char *pname;
5865 TALLOC_CTX *mem_ctx = NULL;
5866 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5868 /* If user is NULL then use the current_user structure */
5870 /* Always allow root or SE_PRINT_OPERATROR to do anything */
5872 if (server_info->utok.uid == sec_initial_uid()
5873 || user_has_privileges(server_info->ptok, &se_printop ) ) {
5874 return True;
5877 /* Get printer name */
5879 pname = PRINTERNAME(snum);
5881 if (!pname || !*pname) {
5882 errno = EACCES;
5883 return False;
5886 /* Get printer security descriptor */
5888 if(!(mem_ctx = talloc_init("print_access_check"))) {
5889 errno = ENOMEM;
5890 return False;
5893 if (!nt_printing_getsec(mem_ctx, pname, &secdesc)) {
5894 talloc_destroy(mem_ctx);
5895 errno = ENOMEM;
5896 return False;
5899 if (access_type == JOB_ACCESS_ADMINISTER) {
5900 SEC_DESC_BUF *parent_secdesc = secdesc;
5902 /* Create a child security descriptor to check permissions
5903 against. This is because print jobs are child objects
5904 objects of a printer. */
5906 status = se_create_child_secdesc_buf(mem_ctx, &secdesc, parent_secdesc->sd, False);
5908 if (!NT_STATUS_IS_OK(status)) {
5909 talloc_destroy(mem_ctx);
5910 errno = map_errno_from_nt_status(status);
5911 return False;
5914 map_job_permissions(secdesc->sd);
5915 } else {
5916 map_printer_permissions(secdesc->sd);
5919 /* Check access */
5920 status = se_access_check(secdesc->sd, server_info->ptok, access_type,
5921 &access_granted);
5923 DEBUG(4, ("access check was %s\n", NT_STATUS_IS_OK(status) ? "SUCCESS" : "FAILURE"));
5925 /* see if we need to try the printer admin list */
5927 if (!NT_STATUS_IS_OK(status) &&
5928 (token_contains_name_in_list(uidtoname(server_info->utok.uid),
5929 NULL, NULL, server_info->ptok,
5930 lp_printer_admin(snum)))) {
5931 talloc_destroy(mem_ctx);
5932 return True;
5935 talloc_destroy(mem_ctx);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 errno = EACCES;
5941 return NT_STATUS_IS_OK(status);
5944 /****************************************************************************
5945 Check the time parameters allow a print operation.
5946 *****************************************************************************/
5948 bool print_time_access_check(const char *servicename)
5950 NT_PRINTER_INFO_LEVEL *printer = NULL;
5951 bool ok = False;
5952 time_t now = time(NULL);
5953 struct tm *t;
5954 uint32 mins;
5956 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
5957 return False;
5959 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5960 ok = True;
5962 t = gmtime(&now);
5963 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5965 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5966 ok = True;
5968 free_a_printer(&printer, 2);
5970 if (!ok)
5971 errno = EACCES;
5973 return ok;
5976 /****************************************************************************
5977 Fill in the servername sent in the _spoolss_open_printer_ex() call
5978 ****************************************************************************/
5980 char* get_server_name( Printer_entry *printer )
5982 return printer->servername;