r551: BUG 1293: fix double free in printer publishing code
[Samba/bb.git] / source / printing / nt_printing.c
blob0670b2543eb36bce2c181fd58edd04c19758ec30
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-2003.
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 2 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, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 STANDARD_MAPPING printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 STANDARD_MAPPING printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 struct table_node {
202 const char *long_archi;
203 const char *short_archi;
204 int version;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
220 {NULL, "", -1 }
223 static BOOL upgrade_to_version_3(void)
225 TDB_DATA kbuf, newkey, dbuf;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
232 dbuf = tdb_fetch(tdb_drivers, kbuf);
234 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237 SAFE_FREE(dbuf.dptr);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
239 return False;
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244 return False;
248 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251 SAFE_FREE(dbuf.dptr);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
253 return False;
255 if (tdb_delete(tdb_drivers, kbuf) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
258 return False;
262 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265 SAFE_FREE(dbuf.dptr);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
267 return False;
269 if (tdb_delete(tdb_drivers, kbuf) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
272 return False;
276 SAFE_FREE(dbuf.dptr);
279 return True;
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL nt_printing_init(void)
288 static pid_t local_pid;
289 const char *vstring = "INFO/version";
291 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
292 return True;
294 if (tdb_drivers)
295 tdb_close(tdb_drivers);
296 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
297 if (!tdb_drivers) {
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno) ));
300 return False;
303 if (tdb_printers)
304 tdb_close(tdb_printers);
305 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
306 if (!tdb_printers) {
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno) ));
309 return False;
312 if (tdb_forms)
313 tdb_close(tdb_forms);
314 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
315 if (!tdb_forms) {
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno) ));
318 return False;
321 local_pid = sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers, vstring, 0);
326 int32 vers_id;
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334 vers_id = NTDRIVERS_DATABASE_VERSION;
337 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
339 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
340 if (!upgrade_to_version_3())
341 return False;
342 } else
343 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
345 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
348 tdb_unlock_bystring(tdb_drivers, vstring);
350 update_c_setprinter(True);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
367 return True;
370 /*******************************************************************
371 Function to allow filename parsing "the old way".
372 ********************************************************************/
374 static BOOL driver_unix_convert(char *name,connection_struct *conn,
375 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
377 unix_format(name);
378 unix_clean_name(name);
379 trim_string(name,"/","/");
380 return unix_convert(name, conn, saved_last_component, bad_path, pst);
383 /*******************************************************************
384 tdb traversal function for counting printers.
385 ********************************************************************/
387 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
388 TDB_DATA data, void *context)
390 int *printer_count = (int*)context;
392 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
393 (*printer_count)++;
394 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
397 return 0;
400 /*******************************************************************
401 Update the spooler global c_setprinter. This variable is initialized
402 when the parent smbd starts with the number of existing printers. It
403 is monotonically increased by the current number of printers *after*
404 each add or delete printer RPC. Only Microsoft knows why... JRR020119
405 ********************************************************************/
407 uint32 update_c_setprinter(BOOL initialize)
409 int32 c_setprinter;
410 int32 printer_count = 0;
412 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
414 /* Traverse the tdb, counting the printers */
415 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
417 /* If initializing, set c_setprinter to current printers count
418 * otherwise, bump it by the current printer count
420 if (!initialize)
421 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
422 else
423 c_setprinter = printer_count;
425 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
426 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
428 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
430 return (uint32)c_setprinter;
433 /*******************************************************************
434 Get the spooler global c_setprinter, accounting for initialization.
435 ********************************************************************/
437 uint32 get_c_setprinter(void)
439 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
441 if (c_setprinter == (int32)-1)
442 c_setprinter = update_c_setprinter(True);
444 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
446 return (uint32)c_setprinter;
449 /****************************************************************************
450 Get builtin form struct list.
451 ****************************************************************************/
453 int get_builtin_ntforms(nt_forms_struct **list)
455 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
456 return sizeof(default_forms) / sizeof(default_forms[0]);
459 /****************************************************************************
460 get a builtin form struct
461 ****************************************************************************/
463 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
465 int i,count;
466 fstring form_name;
467 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
468 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
469 count = sizeof(default_forms) / sizeof(default_forms[0]);
470 for (i=0;i<count;i++) {
471 if (strequal(form_name,default_forms[i].name)) {
472 DEBUGADD(6,("Found builtin form %s \n", form_name));
473 memcpy(form,&default_forms[i],sizeof(*form));
474 break;
478 return (i !=count);
481 /****************************************************************************
482 get a form struct list
483 ****************************************************************************/
484 int get_ntforms(nt_forms_struct **list)
486 TDB_DATA kbuf, newkey, dbuf;
487 nt_forms_struct *tl;
488 nt_forms_struct form;
489 int ret;
490 int i;
491 int n = 0;
493 for (kbuf = tdb_firstkey(tdb_forms);
494 kbuf.dptr;
495 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
497 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
498 continue;
500 dbuf = tdb_fetch(tdb_forms, kbuf);
501 if (!dbuf.dptr)
502 continue;
504 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
505 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
506 &i, &form.flag, &form.width, &form.length, &form.left,
507 &form.top, &form.right, &form.bottom);
508 SAFE_FREE(dbuf.dptr);
509 if (ret != dbuf.dsize)
510 continue;
512 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
513 if (!tl) {
514 DEBUG(0,("get_ntforms: Realloc fail.\n"));
515 return 0;
517 *list = tl;
518 (*list)[n] = form;
519 n++;
523 return n;
526 /****************************************************************************
527 write a form struct list
528 ****************************************************************************/
529 int write_ntforms(nt_forms_struct **list, int number)
531 pstring buf, key;
532 int len;
533 TDB_DATA kbuf,dbuf;
534 int i;
536 for (i=0;i<number;i++) {
537 /* save index, so list is rebuilt in correct order */
538 len = tdb_pack(buf, sizeof(buf), "dddddddd",
539 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
540 (*list)[i].left, (*list)[i].top, (*list)[i].right,
541 (*list)[i].bottom);
542 if (len > sizeof(buf)) break;
543 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
544 kbuf.dsize = strlen(key)+1;
545 kbuf.dptr = key;
546 dbuf.dsize = len;
547 dbuf.dptr = buf;
548 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
551 return i;
554 /****************************************************************************
555 add a form struct at the end of the list
556 ****************************************************************************/
557 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
559 int n=0;
560 BOOL update;
561 fstring form_name;
562 nt_forms_struct *tl;
565 * NT tries to add forms even when
566 * they are already in the base
567 * only update the values if already present
570 update=False;
572 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
573 for (n=0; n<*count; n++) {
574 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
575 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
576 update=True;
577 break;
581 if (update==False) {
582 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
583 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
584 return False;
586 *list = tl;
587 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
588 (*count)++;
591 (*list)[n].flag=form->flags;
592 (*list)[n].width=form->size_x;
593 (*list)[n].length=form->size_y;
594 (*list)[n].left=form->left;
595 (*list)[n].top=form->top;
596 (*list)[n].right=form->right;
597 (*list)[n].bottom=form->bottom;
599 return True;
602 /****************************************************************************
603 Delete a named form struct.
604 ****************************************************************************/
606 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
608 pstring key;
609 TDB_DATA kbuf;
610 int n=0;
611 fstring form_name;
613 *ret = WERR_OK;
615 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
617 for (n=0; n<*count; n++) {
618 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
619 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
620 break;
624 if (n == *count) {
625 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
626 *ret = WERR_INVALID_PARAM;
627 return False;
630 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
631 kbuf.dsize = strlen(key)+1;
632 kbuf.dptr = key;
633 if (tdb_delete(tdb_forms, kbuf) != 0) {
634 *ret = WERR_NOMEM;
635 return False;
638 return True;
641 /****************************************************************************
642 Update a form struct.
643 ****************************************************************************/
645 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
647 int n=0;
648 fstring form_name;
649 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
651 DEBUG(106, ("[%s]\n", form_name));
652 for (n=0; n<count; n++) {
653 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
654 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
655 break;
658 if (n==count) return;
660 (*list)[n].flag=form->flags;
661 (*list)[n].width=form->size_x;
662 (*list)[n].length=form->size_y;
663 (*list)[n].left=form->left;
664 (*list)[n].top=form->top;
665 (*list)[n].right=form->right;
666 (*list)[n].bottom=form->bottom;
669 /****************************************************************************
670 Get the nt drivers list.
671 Traverse the database and look-up the matching names.
672 ****************************************************************************/
673 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
675 int total=0;
676 const char *short_archi;
677 fstring *fl;
678 pstring key;
679 TDB_DATA kbuf, newkey;
681 short_archi = get_short_archi(architecture);
682 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
684 for (kbuf = tdb_firstkey(tdb_drivers);
685 kbuf.dptr;
686 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
688 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
689 continue;
691 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
692 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
693 return -1;
695 else *list = fl;
697 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
698 total++;
701 return(total);
704 /****************************************************************************
705 function to do the mapping between the long architecture name and
706 the short one.
707 ****************************************************************************/
708 const char *get_short_archi(const char *long_archi)
710 int i=-1;
712 DEBUG(107,("Getting architecture dependant directory\n"));
713 do {
714 i++;
715 } while ( (archi_table[i].long_archi!=NULL ) &&
716 StrCaseCmp(long_archi, archi_table[i].long_archi) );
718 if (archi_table[i].long_archi==NULL) {
719 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
720 return NULL;
723 /* this might be client code - but shouldn't this be an fstrcpy etc? */
726 DEBUGADD(108,("index: [%d]\n", i));
727 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
728 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
730 return archi_table[i].short_archi;
733 /****************************************************************************
734 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
735 There are two case to be covered here: PE (Portable Executable) and NE (New
736 Executable) files. Both files support the same INFO structure, but PE files
737 store the signature in unicode, and NE files store it as !unicode.
738 returns -1 on error, 1 on version info found, and 0 on no version info found.
739 ****************************************************************************/
741 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
743 int i;
744 char *buf = NULL;
745 ssize_t byte_count;
747 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
748 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
749 fname, PE_HEADER_SIZE));
750 goto error_exit;
753 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
754 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
755 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
756 fname, (unsigned long)byte_count));
757 goto no_version_info;
760 /* Is this really a DOS header? */
761 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
762 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
763 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
764 goto no_version_info;
767 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
768 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
769 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
770 fname, errno));
771 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
772 goto no_version_info;
775 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
776 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
777 fname, (unsigned long)byte_count));
778 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
779 goto no_version_info;
782 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
783 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
784 unsigned int num_sections;
785 unsigned int section_table_bytes;
787 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
788 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
789 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
790 /* At this point, we assume the file is in error. It still could be somthing
791 * else besides a PE file, but it unlikely at this point.
793 goto error_exit;
796 /* get the section table */
797 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
798 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
799 if (section_table_bytes == 0)
800 goto error_exit;
802 SAFE_FREE(buf);
803 if ((buf=malloc(section_table_bytes)) == NULL) {
804 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
805 fname, section_table_bytes));
806 goto error_exit;
809 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
810 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
811 fname, (unsigned long)byte_count));
812 goto error_exit;
815 /* Iterate the section table looking for the resource section ".rsrc" */
816 for (i = 0; i < num_sections; i++) {
817 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
819 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
820 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
821 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
823 if (section_bytes == 0)
824 goto error_exit;
826 SAFE_FREE(buf);
827 if ((buf=malloc(section_bytes)) == NULL) {
828 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
829 fname, section_bytes));
830 goto error_exit;
833 /* Seek to the start of the .rsrc section info */
834 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
835 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
836 fname, errno));
837 goto error_exit;
840 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
841 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
842 fname, (unsigned long)byte_count));
843 goto error_exit;
846 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
847 goto error_exit;
849 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
850 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
851 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
852 /* Align to next long address */
853 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
855 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
856 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
857 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
859 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
860 fname, *major, *minor,
861 (*major>>16)&0xffff, *major&0xffff,
862 (*minor>>16)&0xffff, *minor&0xffff));
863 SAFE_FREE(buf);
864 return 1;
871 /* Version info not found, fall back to origin date/time */
872 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
873 SAFE_FREE(buf);
874 return 0;
876 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
877 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
878 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
879 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
880 /* At this point, we assume the file is in error. It still could be somthing
881 * else besides a NE file, but it unlikely at this point. */
882 goto error_exit;
885 /* Allocate a bit more space to speed up things */
886 SAFE_FREE(buf);
887 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
888 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
889 fname, PE_HEADER_SIZE));
890 goto error_exit;
893 /* This is a HACK! I got tired of trying to sort through the messy
894 * 'NE' file format. If anyone wants to clean this up please have at
895 * it, but this works. 'NE' files will eventually fade away. JRR */
896 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
897 /* Cover case that should not occur in a well formed 'NE' .dll file */
898 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
900 for(i=0; i<byte_count; i++) {
901 /* Fast skip past data that can't possibly match */
902 if (buf[i] != 'V') continue;
904 /* Potential match data crosses buf boundry, move it to beginning
905 * of buf, and fill the buf with as much as it will hold. */
906 if (i>byte_count-VS_VERSION_INFO_SIZE) {
907 int bc;
909 memcpy(buf, &buf[i], byte_count-i);
910 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
911 (byte_count-i))) < 0) {
913 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
914 fname, errno));
915 goto error_exit;
918 byte_count = bc + (byte_count - i);
919 if (byte_count<VS_VERSION_INFO_SIZE) break;
921 i = 0;
924 /* Check that the full signature string and the magic number that
925 * follows exist (not a perfect solution, but the chances that this
926 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
927 * twice, as it is simpler to read the code. */
928 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
929 /* Compute skip alignment to next long address */
930 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
931 sizeof(VS_SIGNATURE)) & 3;
932 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
934 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
935 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
936 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
937 fname, *major, *minor,
938 (*major>>16)&0xffff, *major&0xffff,
939 (*minor>>16)&0xffff, *minor&0xffff));
940 SAFE_FREE(buf);
941 return 1;
946 /* Version info not found, fall back to origin date/time */
947 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
948 SAFE_FREE(buf);
949 return 0;
951 } else
952 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
953 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
954 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
956 no_version_info:
957 SAFE_FREE(buf);
958 return 0;
960 error_exit:
961 SAFE_FREE(buf);
962 return -1;
965 /****************************************************************************
966 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
967 share one or more files. During the MS installation process files are checked
968 to insure that only a newer version of a shared file is installed over an
969 older version. There are several possibilities for this comparison. If there
970 is no previous version, the new one is newer (obviously). If either file is
971 missing the version info structure, compare the creation date (on Unix use
972 the modification date). Otherwise chose the numerically larger version number.
973 ****************************************************************************/
975 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
977 BOOL use_version = True;
978 pstring filepath;
980 uint32 new_major;
981 uint32 new_minor;
982 time_t new_create_time;
984 uint32 old_major;
985 uint32 old_minor;
986 time_t old_create_time;
988 int access_mode;
989 int action;
990 files_struct *fsp = NULL;
991 SMB_STRUCT_STAT st;
992 SMB_STRUCT_STAT stat_buf;
993 BOOL bad_path;
995 ZERO_STRUCT(st);
996 ZERO_STRUCT(stat_buf);
997 new_create_time = (time_t)0;
998 old_create_time = (time_t)0;
1000 /* Get file version info (if available) for previous file (if it exists) */
1001 pstrcpy(filepath, old_file);
1003 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1005 fsp = open_file_shared(conn, filepath, &stat_buf,
1006 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1007 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1008 FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
1009 if (!fsp) {
1010 /* Old file not found, so by definition new file is in fact newer */
1011 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1012 filepath, errno));
1013 return True;
1015 } else {
1016 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1017 if (ret == -1) goto error_exit;
1019 if (!ret) {
1020 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1021 old_file));
1022 use_version = False;
1023 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1024 old_create_time = st.st_mtime;
1025 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1028 close_file(fsp, True);
1030 /* Get file version info (if available) for new file */
1031 pstrcpy(filepath, new_file);
1032 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1034 fsp = open_file_shared(conn, filepath, &stat_buf,
1035 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1036 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1037 FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
1038 if (!fsp) {
1039 /* New file not found, this shouldn't occur if the caller did its job */
1040 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1041 filepath, errno));
1042 goto error_exit;
1044 } else {
1045 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1046 if (ret == -1) goto error_exit;
1048 if (!ret) {
1049 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1050 new_file));
1051 use_version = False;
1052 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1053 new_create_time = st.st_mtime;
1054 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1057 close_file(fsp, True);
1059 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1060 /* Compare versions and choose the larger version number */
1061 if (new_major > old_major ||
1062 (new_major == old_major && new_minor > old_minor)) {
1064 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1065 return True;
1067 else {
1068 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1069 return False;
1072 } else {
1073 /* Compare modification time/dates and choose the newest time/date */
1074 if (new_create_time > old_create_time) {
1075 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1076 return True;
1078 else {
1079 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1080 return False;
1084 error_exit:
1085 if(fsp)
1086 close_file(fsp, True);
1087 return -1;
1090 /****************************************************************************
1091 Determine the correct cVersion associated with an architecture and driver
1092 ****************************************************************************/
1093 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1094 struct current_user *user, WERROR *perr)
1096 int cversion;
1097 int access_mode;
1098 int action;
1099 NTSTATUS nt_status;
1100 pstring driverpath;
1101 DATA_BLOB null_pw;
1102 fstring res_type;
1103 files_struct *fsp = NULL;
1104 BOOL bad_path;
1105 SMB_STRUCT_STAT st;
1106 connection_struct *conn;
1108 ZERO_STRUCT(st);
1110 *perr = WERR_INVALID_PARAM;
1112 /* If architecture is Windows 95/98/ME, the version is always 0. */
1113 if (strcmp(architecture, "WIN40") == 0) {
1114 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1115 *perr = WERR_OK;
1116 return 0;
1120 * Connect to the print$ share under the same account as the user connected
1121 * to the rpc pipe. Note we must still be root to do this.
1124 /* Null password is ok - we are already an authenticated user... */
1125 null_pw = data_blob(NULL, 0);
1126 fstrcpy(res_type, "A:");
1127 become_root();
1128 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1129 unbecome_root();
1131 if (conn == NULL) {
1132 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1133 *perr = ntstatus_to_werror(nt_status);
1134 return -1;
1137 /* We are temporarily becoming the connection user. */
1138 if (!become_user(conn, user->vuid)) {
1139 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1140 *perr = WERR_ACCESS_DENIED;
1141 return -1;
1144 /* Open the driver file (Portable Executable format) and determine the
1145 * deriver the cversion. */
1146 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1148 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1150 fsp = open_file_shared(conn, driverpath, &st,
1151 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1152 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1153 FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
1154 if (!fsp) {
1155 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1156 driverpath, errno));
1157 *perr = WERR_ACCESS_DENIED;
1158 goto error_exit;
1160 else {
1161 uint32 major;
1162 uint32 minor;
1163 int ret = get_file_version(fsp, driverpath, &major, &minor);
1164 if (ret == -1) goto error_exit;
1166 if (!ret) {
1167 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1168 goto error_exit;
1172 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1173 * for more details. Version in this case is not just the version of the
1174 * file, but the version in the sense of kernal mode (2) vs. user mode
1175 * (3) drivers. Other bits of the version fields are the version info.
1176 * JRR 010716
1178 cversion = major & 0x0000ffff;
1179 switch (cversion) {
1180 case 2: /* WinNT drivers */
1181 case 3: /* Win2K drivers */
1182 break;
1184 default:
1185 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1186 driverpath, cversion));
1187 goto error_exit;
1190 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1191 driverpath, major, minor));
1194 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1195 driverpath, cversion));
1197 close_file(fsp, True);
1198 close_cnum(conn, user->vuid);
1199 unbecome_user();
1200 *perr = WERR_OK;
1201 return cversion;
1204 error_exit:
1206 if(fsp)
1207 close_file(fsp, True);
1209 close_cnum(conn, user->vuid);
1210 unbecome_user();
1211 return -1;
1214 /****************************************************************************
1215 ****************************************************************************/
1216 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1217 struct current_user *user)
1219 const char *architecture;
1220 fstring new_name;
1221 char *p;
1222 int i;
1223 WERROR err;
1225 /* clean up the driver name.
1226 * we can get .\driver.dll
1227 * or worse c:\windows\system\driver.dll !
1229 /* using an intermediate string to not have overlaping memcpy()'s */
1230 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1231 fstrcpy(new_name, p+1);
1232 fstrcpy(driver->driverpath, new_name);
1235 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1236 fstrcpy(new_name, p+1);
1237 fstrcpy(driver->datafile, new_name);
1240 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1241 fstrcpy(new_name, p+1);
1242 fstrcpy(driver->configfile, new_name);
1245 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1246 fstrcpy(new_name, p+1);
1247 fstrcpy(driver->helpfile, new_name);
1250 if (driver->dependentfiles) {
1251 for (i=0; *driver->dependentfiles[i]; i++) {
1252 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1253 fstrcpy(new_name, p+1);
1254 fstrcpy(driver->dependentfiles[i], new_name);
1259 architecture = get_short_archi(driver->environment);
1261 /* jfm:7/16/2000 the client always sends the cversion=0.
1262 * The server should check which version the driver is by reading
1263 * the PE header of driver->driverpath.
1265 * For Windows 95/98 the version is 0 (so the value sent is correct)
1266 * For Windows NT (the architecture doesn't matter)
1267 * NT 3.1: cversion=0
1268 * NT 3.5/3.51: cversion=1
1269 * NT 4: cversion=2
1270 * NT2K: cversion=3
1272 if ((driver->cversion = get_correct_cversion( architecture,
1273 driver->driverpath, user, &err)) == -1)
1274 return err;
1276 return WERR_OK;
1279 /****************************************************************************
1280 ****************************************************************************/
1281 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1283 const char *architecture;
1284 fstring new_name;
1285 char *p;
1286 int i;
1287 WERROR err;
1289 /* clean up the driver name.
1290 * we can get .\driver.dll
1291 * or worse c:\windows\system\driver.dll !
1293 /* using an intermediate string to not have overlaping memcpy()'s */
1294 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1295 fstrcpy(new_name, p+1);
1296 fstrcpy(driver->driverpath, new_name);
1299 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1300 fstrcpy(new_name, p+1);
1301 fstrcpy(driver->datafile, new_name);
1304 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1305 fstrcpy(new_name, p+1);
1306 fstrcpy(driver->configfile, new_name);
1309 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1310 fstrcpy(new_name, p+1);
1311 fstrcpy(driver->helpfile, new_name);
1314 if (driver->dependentfiles) {
1315 for (i=0; *driver->dependentfiles[i]; i++) {
1316 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1317 fstrcpy(new_name, p+1);
1318 fstrcpy(driver->dependentfiles[i], new_name);
1323 architecture = get_short_archi(driver->environment);
1325 /* jfm:7/16/2000 the client always sends the cversion=0.
1326 * The server should check which version the driver is by reading
1327 * the PE header of driver->driverpath.
1329 * For Windows 95/98 the version is 0 (so the value sent is correct)
1330 * For Windows NT (the architecture doesn't matter)
1331 * NT 3.1: cversion=0
1332 * NT 3.5/3.51: cversion=1
1333 * NT 4: cversion=2
1334 * NT2K: cversion=3
1336 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1337 return err;
1339 return WERR_OK;
1342 /****************************************************************************
1343 ****************************************************************************/
1344 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1345 uint32 level, struct current_user *user)
1347 switch (level) {
1348 case 3:
1350 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1351 driver=driver_abstract.info_3;
1352 return clean_up_driver_struct_level_3(driver, user);
1354 case 6:
1356 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1357 driver=driver_abstract.info_6;
1358 return clean_up_driver_struct_level_6(driver, user);
1360 default:
1361 return WERR_INVALID_PARAM;
1365 /****************************************************************************
1366 This function sucks and should be replaced. JRA.
1367 ****************************************************************************/
1369 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1371 dst->cversion = src->version;
1373 fstrcpy( dst->name, src->name);
1374 fstrcpy( dst->environment, src->environment);
1375 fstrcpy( dst->driverpath, src->driverpath);
1376 fstrcpy( dst->datafile, src->datafile);
1377 fstrcpy( dst->configfile, src->configfile);
1378 fstrcpy( dst->helpfile, src->helpfile);
1379 fstrcpy( dst->monitorname, src->monitorname);
1380 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1381 dst->dependentfiles = src->dependentfiles;
1384 #if 0 /* Debugging function */
1386 static char* ffmt(unsigned char *c){
1387 int i;
1388 static char ffmt_str[17];
1390 for (i=0; i<16; i++) {
1391 if ((c[i] < ' ') || (c[i] > '~'))
1392 ffmt_str[i]='.';
1393 else
1394 ffmt_str[i]=c[i];
1396 ffmt_str[16]='\0';
1397 return ffmt_str;
1400 #endif
1402 /****************************************************************************
1403 ****************************************************************************/
1404 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1405 struct current_user *user, WERROR *perr)
1407 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1408 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1409 const char *architecture;
1410 pstring new_dir;
1411 pstring old_name;
1412 pstring new_name;
1413 DATA_BLOB null_pw;
1414 connection_struct *conn;
1415 NTSTATUS nt_status;
1416 pstring inbuf;
1417 pstring outbuf;
1418 fstring res_type;
1419 BOOL bad_path;
1420 SMB_STRUCT_STAT st;
1421 int ver = 0;
1422 int i;
1424 memset(inbuf, '\0', sizeof(inbuf));
1425 memset(outbuf, '\0', sizeof(outbuf));
1426 *perr = WERR_OK;
1428 if (level==3)
1429 driver=driver_abstract.info_3;
1430 else if (level==6) {
1431 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1432 driver = &converted_driver;
1433 } else {
1434 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1435 return False;
1438 architecture = get_short_archi(driver->environment);
1441 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1442 * Note we must be root to do this.
1445 null_pw = data_blob(NULL, 0);
1446 fstrcpy(res_type, "A:");
1447 become_root();
1448 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1449 unbecome_root();
1451 if (conn == NULL) {
1452 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1453 *perr = ntstatus_to_werror(nt_status);
1454 return False;
1458 * Save who we are - we are temporarily becoming the connection user.
1461 if (!become_user(conn, conn->vuid)) {
1462 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1463 return False;
1467 * make the directories version and version\driver_name
1468 * under the architecture directory.
1470 DEBUG(5,("Creating first directory\n"));
1471 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1472 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1473 mkdir_internal(conn, new_dir);
1475 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1476 * listed for this driver which has already been moved, skip it (note:
1477 * drivers may list the same file name several times. Then check if the
1478 * file already exists in archi\cversion\, if so, check that the version
1479 * info (or time stamps if version info is unavailable) is newer (or the
1480 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1481 * Otherwise, delete the file.
1483 * If a file is not moved to archi\cversion\ because of an error, all the
1484 * rest of the 'unmoved' driver files are removed from archi\. If one or
1485 * more of the driver's files was already moved to archi\cversion\, it
1486 * potentially leaves the driver in a partially updated state. Version
1487 * trauma will most likely occur if an client attempts to use any printer
1488 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1489 * done is appropriate... later JRR
1492 DEBUG(5,("Moving files now !\n"));
1494 if (driver->driverpath && strlen(driver->driverpath)) {
1495 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1496 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1497 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1498 NTSTATUS status;
1499 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1500 status = rename_internals(conn, new_name, old_name, 0, True);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1503 new_name, old_name));
1504 *perr = ntstatus_to_werror(status);
1505 unlink_internals(conn, 0, new_name);
1506 ver = -1;
1508 } else {
1509 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1510 unlink_internals(conn, 0, new_name);
1514 if (driver->datafile && strlen(driver->datafile)) {
1515 if (!strequal(driver->datafile, driver->driverpath)) {
1516 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1517 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1518 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1519 NTSTATUS status;
1520 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1521 status = rename_internals(conn, new_name, old_name, 0, True);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1524 new_name, old_name));
1525 *perr = ntstatus_to_werror(status);
1526 unlink_internals(conn, 0, new_name);
1527 ver = -1;
1529 } else {
1530 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1531 unlink_internals(conn, 0, new_name);
1536 if (driver->configfile && strlen(driver->configfile)) {
1537 if (!strequal(driver->configfile, driver->driverpath) &&
1538 !strequal(driver->configfile, driver->datafile)) {
1539 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1540 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1541 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1542 NTSTATUS status;
1543 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1544 status = rename_internals(conn, new_name, old_name, 0, True);
1545 if (!NT_STATUS_IS_OK(status)) {
1546 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1547 new_name, old_name));
1548 *perr = ntstatus_to_werror(status);
1549 unlink_internals(conn, 0, new_name);
1550 ver = -1;
1552 } else {
1553 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1554 unlink_internals(conn, 0, new_name);
1559 if (driver->helpfile && strlen(driver->helpfile)) {
1560 if (!strequal(driver->helpfile, driver->driverpath) &&
1561 !strequal(driver->helpfile, driver->datafile) &&
1562 !strequal(driver->helpfile, driver->configfile)) {
1563 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1564 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1565 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1566 NTSTATUS status;
1567 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1568 status = rename_internals(conn, new_name, old_name, 0, True);
1569 if (!NT_STATUS_IS_OK(status)) {
1570 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1571 new_name, old_name));
1572 *perr = ntstatus_to_werror(status);
1573 unlink_internals(conn, 0, new_name);
1574 ver = -1;
1576 } else {
1577 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1578 unlink_internals(conn, 0, new_name);
1583 if (driver->dependentfiles) {
1584 for (i=0; *driver->dependentfiles[i]; i++) {
1585 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1586 !strequal(driver->dependentfiles[i], driver->datafile) &&
1587 !strequal(driver->dependentfiles[i], driver->configfile) &&
1588 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1589 int j;
1590 for (j=0; j < i; j++) {
1591 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1592 goto NextDriver;
1596 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1597 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1598 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1599 NTSTATUS status;
1600 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1601 status = rename_internals(conn, new_name, old_name, 0, True);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1604 new_name, old_name));
1605 *perr = ntstatus_to_werror(status);
1606 unlink_internals(conn, 0, new_name);
1607 ver = -1;
1609 } else {
1610 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1611 unlink_internals(conn, 0, new_name);
1614 NextDriver: ;
1618 close_cnum(conn, user->vuid);
1619 unbecome_user();
1621 return ver == -1 ? False : True;
1624 /****************************************************************************
1625 ****************************************************************************/
1626 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1628 int len, buflen;
1629 const char *architecture;
1630 pstring directory;
1631 fstring temp_name;
1632 pstring key;
1633 char *buf;
1634 int i, ret;
1635 TDB_DATA kbuf, dbuf;
1637 architecture = get_short_archi(driver->environment);
1639 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1640 * \\server is added in the rpc server layer.
1641 * It does make sense to NOT store the server's name in the printer TDB.
1644 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1646 /* .inf files do not always list a file for each of the four standard files.
1647 * Don't prepend a path to a null filename, or client claims:
1648 * "The server on which the printer resides does not have a suitable
1649 * <printer driver name> printer driver installed. Click OK if you
1650 * wish to install the driver on your local machine."
1652 if (strlen(driver->driverpath)) {
1653 fstrcpy(temp_name, driver->driverpath);
1654 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1657 if (strlen(driver->datafile)) {
1658 fstrcpy(temp_name, driver->datafile);
1659 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1662 if (strlen(driver->configfile)) {
1663 fstrcpy(temp_name, driver->configfile);
1664 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1667 if (strlen(driver->helpfile)) {
1668 fstrcpy(temp_name, driver->helpfile);
1669 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1672 if (driver->dependentfiles) {
1673 for (i=0; *driver->dependentfiles[i]; i++) {
1674 fstrcpy(temp_name, driver->dependentfiles[i]);
1675 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1679 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1681 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1683 buf = NULL;
1684 len = buflen = 0;
1686 again:
1687 len = 0;
1688 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1689 driver->cversion,
1690 driver->name,
1691 driver->environment,
1692 driver->driverpath,
1693 driver->datafile,
1694 driver->configfile,
1695 driver->helpfile,
1696 driver->monitorname,
1697 driver->defaultdatatype);
1699 if (driver->dependentfiles) {
1700 for (i=0; *driver->dependentfiles[i]; i++) {
1701 len += tdb_pack(buf+len, buflen-len, "f",
1702 driver->dependentfiles[i]);
1706 if (len != buflen) {
1707 char *tb;
1709 tb = (char *)Realloc(buf, len);
1710 if (!tb) {
1711 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1712 ret = -1;
1713 goto done;
1715 else buf = tb;
1716 buflen = len;
1717 goto again;
1721 kbuf.dptr = key;
1722 kbuf.dsize = strlen(key)+1;
1723 dbuf.dptr = buf;
1724 dbuf.dsize = len;
1726 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1728 done:
1729 if (ret)
1730 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1732 SAFE_FREE(buf);
1733 return ret;
1736 /****************************************************************************
1737 ****************************************************************************/
1738 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1740 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1742 ZERO_STRUCT(info3);
1743 info3.cversion = driver->version;
1744 fstrcpy(info3.name,driver->name);
1745 fstrcpy(info3.environment,driver->environment);
1746 fstrcpy(info3.driverpath,driver->driverpath);
1747 fstrcpy(info3.datafile,driver->datafile);
1748 fstrcpy(info3.configfile,driver->configfile);
1749 fstrcpy(info3.helpfile,driver->helpfile);
1750 fstrcpy(info3.monitorname,driver->monitorname);
1751 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1752 info3.dependentfiles = driver->dependentfiles;
1754 return add_a_printer_driver_3(&info3);
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1762 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1764 ZERO_STRUCT(info);
1766 fstrcpy(info.name, driver);
1767 fstrcpy(info.defaultdatatype, "RAW");
1769 fstrcpy(info.driverpath, "");
1770 fstrcpy(info.datafile, "");
1771 fstrcpy(info.configfile, "");
1772 fstrcpy(info.helpfile, "");
1774 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1775 return WERR_NOMEM;
1777 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1778 fstrcpy(info.dependentfiles[0], "");
1780 *info_ptr = memdup(&info, sizeof(info));
1782 return WERR_OK;
1785 /****************************************************************************
1786 ****************************************************************************/
1787 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1789 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1790 TDB_DATA kbuf, dbuf;
1791 const char *architecture;
1792 int len = 0;
1793 int i;
1794 pstring key;
1796 ZERO_STRUCT(driver);
1798 architecture = get_short_archi(arch);
1800 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1802 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1803 version = 0;
1805 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1807 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1809 kbuf.dptr = key;
1810 kbuf.dsize = strlen(key)+1;
1812 dbuf = tdb_fetch(tdb_drivers, kbuf);
1813 if (!dbuf.dptr)
1814 return WERR_UNKNOWN_PRINTER_DRIVER;
1816 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1817 &driver.cversion,
1818 driver.name,
1819 driver.environment,
1820 driver.driverpath,
1821 driver.datafile,
1822 driver.configfile,
1823 driver.helpfile,
1824 driver.monitorname,
1825 driver.defaultdatatype);
1827 i=0;
1828 while (len < dbuf.dsize) {
1829 fstring *tddfs;
1831 tddfs = (fstring *)Realloc(driver.dependentfiles,
1832 sizeof(fstring)*(i+2));
1833 if (tddfs == NULL) {
1834 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1835 break;
1837 else driver.dependentfiles = tddfs;
1839 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1840 &driver.dependentfiles[i]);
1841 i++;
1844 if (driver.dependentfiles != NULL)
1845 fstrcpy(driver.dependentfiles[i], "");
1847 SAFE_FREE(dbuf.dptr);
1849 if (len != dbuf.dsize) {
1850 SAFE_FREE(driver.dependentfiles);
1852 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1855 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1857 return WERR_OK;
1860 /****************************************************************************
1861 Debugging function, dump at level 6 the struct in the logs.
1862 ****************************************************************************/
1864 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1866 uint32 result;
1867 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1868 int i;
1870 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1872 switch (level)
1874 case 3:
1876 if (driver.info_3 == NULL)
1877 result=5;
1878 else {
1879 info3=driver.info_3;
1881 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1882 DEBUGADD(20,("name:[%s]\n", info3->name));
1883 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1884 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1885 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1886 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1887 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1888 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1889 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1891 for (i=0; info3->dependentfiles &&
1892 *info3->dependentfiles[i]; i++) {
1893 DEBUGADD(20,("dependentfile:[%s]\n",
1894 info3->dependentfiles[i]));
1896 result=0;
1898 break;
1900 default:
1901 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1902 result=1;
1903 break;
1906 return result;
1909 /****************************************************************************
1910 ****************************************************************************/
1911 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1913 int len = 0;
1915 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1917 if (!nt_devmode)
1918 return len;
1920 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1921 nt_devmode->devicename,
1922 nt_devmode->formname,
1924 nt_devmode->specversion,
1925 nt_devmode->driverversion,
1926 nt_devmode->size,
1927 nt_devmode->driverextra,
1928 nt_devmode->orientation,
1929 nt_devmode->papersize,
1930 nt_devmode->paperlength,
1931 nt_devmode->paperwidth,
1932 nt_devmode->scale,
1933 nt_devmode->copies,
1934 nt_devmode->defaultsource,
1935 nt_devmode->printquality,
1936 nt_devmode->color,
1937 nt_devmode->duplex,
1938 nt_devmode->yresolution,
1939 nt_devmode->ttoption,
1940 nt_devmode->collate,
1941 nt_devmode->logpixels,
1943 nt_devmode->fields,
1944 nt_devmode->bitsperpel,
1945 nt_devmode->pelswidth,
1946 nt_devmode->pelsheight,
1947 nt_devmode->displayflags,
1948 nt_devmode->displayfrequency,
1949 nt_devmode->icmmethod,
1950 nt_devmode->icmintent,
1951 nt_devmode->mediatype,
1952 nt_devmode->dithertype,
1953 nt_devmode->reserved1,
1954 nt_devmode->reserved2,
1955 nt_devmode->panningwidth,
1956 nt_devmode->panningheight,
1957 nt_devmode->private);
1960 if (nt_devmode->private) {
1961 len += tdb_pack(buf+len, buflen-len, "B",
1962 nt_devmode->driverextra,
1963 nt_devmode->private);
1966 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1968 return len;
1971 /****************************************************************************
1972 Pack all values in all printer keys
1973 ***************************************************************************/
1975 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1977 int len = 0;
1978 int i, j;
1979 REGISTRY_VALUE *val;
1980 REGVAL_CTR *val_ctr;
1981 pstring path;
1982 int num_values;
1984 if ( !data )
1985 return 0;
1987 /* loop over all keys */
1989 for ( i=0; i<data->num_keys; i++ ) {
1990 val_ctr = &data->keys[i].values;
1991 num_values = regval_ctr_numvals( val_ctr );
1993 /* loop over all values */
1995 for ( j=0; j<num_values; j++ ) {
1996 /* pathname should be stored as <key>\<value> */
1998 val = regval_ctr_specific_value( val_ctr, j );
1999 pstrcpy( path, data->keys[i].name );
2000 pstrcat( path, "\\" );
2001 pstrcat( path, regval_name(val) );
2003 len += tdb_pack(buf+len, buflen-len, "pPdB",
2004 val,
2005 path,
2006 regval_type(val),
2007 regval_size(val),
2008 regval_data_p(val) );
2013 /* terminator */
2015 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2017 return len;
2021 /****************************************************************************
2022 Delete a printer - this just deletes the printer info file, any open
2023 handles are not affected.
2024 ****************************************************************************/
2026 uint32 del_a_printer(char *sharename)
2028 pstring key;
2029 TDB_DATA kbuf;
2031 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2033 kbuf.dptr=key;
2034 kbuf.dsize=strlen(key)+1;
2036 tdb_delete(tdb_printers, kbuf);
2037 return 0;
2040 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2041 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2042 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2043 /****************************************************************************
2044 ****************************************************************************/
2045 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2047 pstring key;
2048 char *buf;
2049 int buflen, len;
2050 WERROR ret;
2051 TDB_DATA kbuf, dbuf;
2054 * in addprinter: no servername and the printer is the name
2055 * in setprinter: servername is \\server
2056 * and printer is \\server\\printer
2058 * Samba manages only local printers.
2059 * we currently don't support things like path=\\other_server\printer
2062 if (info->servername[0]!='\0') {
2063 trim_string(info->printername, info->servername, NULL);
2064 trim_char(info->printername, '\\', '\0');
2065 info->servername[0]='\0';
2069 * JFM: one day I'll forget.
2070 * below that's info->portname because that's the SAMBA sharename
2071 * and I made NT 'thinks' it's the portname
2072 * the info->sharename is the thing you can name when you add a printer
2073 * that's the short-name when you create shared printer for 95/98
2074 * So I've made a limitation in SAMBA: you can only have 1 printer model
2075 * behind a SAMBA share.
2078 buf = NULL;
2079 buflen = 0;
2081 again:
2082 len = 0;
2083 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2084 info->attributes,
2085 info->priority,
2086 info->default_priority,
2087 info->starttime,
2088 info->untiltime,
2089 info->status,
2090 info->cjobs,
2091 info->averageppm,
2092 info->changeid,
2093 info->c_setprinter,
2094 info->setuptime,
2095 info->servername,
2096 info->printername,
2097 info->sharename,
2098 info->portname,
2099 info->drivername,
2100 info->comment,
2101 info->location,
2102 info->sepfile,
2103 info->printprocessor,
2104 info->datatype,
2105 info->parameters);
2107 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2109 len += pack_values( &info->data, buf+len, buflen-len );
2111 if (buflen != len) {
2112 char *tb;
2114 tb = (char *)Realloc(buf, len);
2115 if (!tb) {
2116 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2117 ret = WERR_NOMEM;
2118 goto done;
2120 else buf = tb;
2121 buflen = len;
2122 goto again;
2126 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2128 kbuf.dptr = key;
2129 kbuf.dsize = strlen(key)+1;
2130 dbuf.dptr = buf;
2131 dbuf.dsize = len;
2133 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2135 done:
2136 if (!W_ERROR_IS_OK(ret))
2137 DEBUG(8, ("error updating printer to tdb on disk\n"));
2139 SAFE_FREE(buf);
2141 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2142 info->sharename, info->drivername, info->portname, len));
2144 return ret;
2148 /****************************************************************************
2149 Malloc and return an NT devicemode.
2150 ****************************************************************************/
2152 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2155 char adevice[MAXDEVICENAME];
2156 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2158 if (nt_devmode == NULL) {
2159 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2160 return NULL;
2163 ZERO_STRUCTP(nt_devmode);
2165 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2166 fstrcpy(nt_devmode->devicename, adevice);
2168 fstrcpy(nt_devmode->formname, "Letter");
2170 nt_devmode->specversion = 0x0401;
2171 nt_devmode->driverversion = 0x0400;
2172 nt_devmode->size = 0x00DC;
2173 nt_devmode->driverextra = 0x0000;
2174 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2175 DEFAULTSOURCE | COPIES | SCALE |
2176 PAPERSIZE | ORIENTATION;
2177 nt_devmode->orientation = 1;
2178 nt_devmode->papersize = PAPER_LETTER;
2179 nt_devmode->paperlength = 0;
2180 nt_devmode->paperwidth = 0;
2181 nt_devmode->scale = 0x64;
2182 nt_devmode->copies = 1;
2183 nt_devmode->defaultsource = BIN_FORMSOURCE;
2184 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2185 nt_devmode->color = COLOR_MONOCHROME;
2186 nt_devmode->duplex = DUP_SIMPLEX;
2187 nt_devmode->yresolution = 0;
2188 nt_devmode->ttoption = TT_SUBDEV;
2189 nt_devmode->collate = COLLATE_FALSE;
2190 nt_devmode->icmmethod = 0;
2191 nt_devmode->icmintent = 0;
2192 nt_devmode->mediatype = 0;
2193 nt_devmode->dithertype = 0;
2195 /* non utilisés par un driver d'imprimante */
2196 nt_devmode->logpixels = 0;
2197 nt_devmode->bitsperpel = 0;
2198 nt_devmode->pelswidth = 0;
2199 nt_devmode->pelsheight = 0;
2200 nt_devmode->displayflags = 0;
2201 nt_devmode->displayfrequency = 0;
2202 nt_devmode->reserved1 = 0;
2203 nt_devmode->reserved2 = 0;
2204 nt_devmode->panningwidth = 0;
2205 nt_devmode->panningheight = 0;
2207 nt_devmode->private = NULL;
2208 return nt_devmode;
2211 /****************************************************************************
2212 Deepcopy an NT devicemode.
2213 ****************************************************************************/
2215 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2217 NT_DEVICEMODE *new_nt_devicemode = NULL;
2219 if ( !nt_devicemode )
2220 return NULL;
2222 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2223 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2224 return NULL;
2227 new_nt_devicemode->private = NULL;
2228 if (nt_devicemode->private != NULL) {
2229 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2230 SAFE_FREE(new_nt_devicemode);
2231 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2232 return NULL;
2236 return new_nt_devicemode;
2239 /****************************************************************************
2240 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2241 ****************************************************************************/
2243 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2245 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2247 if(nt_devmode == NULL)
2248 return;
2250 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2252 SAFE_FREE(nt_devmode->private);
2253 SAFE_FREE(*devmode_ptr);
2256 /****************************************************************************
2257 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2258 ****************************************************************************/
2259 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2261 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2262 NT_PRINTER_DATA *data;
2263 int i;
2265 if ( !info )
2266 return;
2268 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2270 free_nt_devicemode(&info->devmode);
2272 /* clean up all registry keys */
2274 data = &info->data;
2275 for ( i=0; i<data->num_keys; i++ ) {
2276 SAFE_FREE( data->keys[i].name );
2277 regval_ctr_destroy( &data->keys[i].values );
2279 SAFE_FREE( data->keys );
2281 /* finally the top level structure */
2283 SAFE_FREE( *info_ptr );
2287 /****************************************************************************
2288 ****************************************************************************/
2289 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2291 int len = 0;
2292 int extra_len = 0;
2293 NT_DEVICEMODE devmode;
2295 ZERO_STRUCT(devmode);
2297 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2299 if (!*nt_devmode) return len;
2301 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2302 devmode.devicename,
2303 devmode.formname,
2305 &devmode.specversion,
2306 &devmode.driverversion,
2307 &devmode.size,
2308 &devmode.driverextra,
2309 &devmode.orientation,
2310 &devmode.papersize,
2311 &devmode.paperlength,
2312 &devmode.paperwidth,
2313 &devmode.scale,
2314 &devmode.copies,
2315 &devmode.defaultsource,
2316 &devmode.printquality,
2317 &devmode.color,
2318 &devmode.duplex,
2319 &devmode.yresolution,
2320 &devmode.ttoption,
2321 &devmode.collate,
2322 &devmode.logpixels,
2324 &devmode.fields,
2325 &devmode.bitsperpel,
2326 &devmode.pelswidth,
2327 &devmode.pelsheight,
2328 &devmode.displayflags,
2329 &devmode.displayfrequency,
2330 &devmode.icmmethod,
2331 &devmode.icmintent,
2332 &devmode.mediatype,
2333 &devmode.dithertype,
2334 &devmode.reserved1,
2335 &devmode.reserved2,
2336 &devmode.panningwidth,
2337 &devmode.panningheight,
2338 &devmode.private);
2340 if (devmode.private) {
2341 /* the len in tdb_unpack is an int value and
2342 * devmode.driverextra is only a short
2344 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2345 devmode.driverextra=(uint16)extra_len;
2347 /* check to catch an invalid TDB entry so we don't segfault */
2348 if (devmode.driverextra == 0) {
2349 devmode.private = NULL;
2353 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2355 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2356 if (devmode.private)
2357 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2359 return len;
2362 /****************************************************************************
2363 Allocate and initialize a new slot.
2364 ***************************************************************************/
2366 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2368 NT_PRINTER_KEY *d;
2369 int key_index;
2371 if ( !data || !name )
2372 return -1;
2374 /* allocate another slot in the NT_PRINTER_KEY array */
2376 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2377 if ( d )
2378 data->keys = d;
2380 key_index = data->num_keys;
2382 /* initialze new key */
2384 data->num_keys++;
2385 data->keys[key_index].name = strdup( name );
2387 ZERO_STRUCTP( &data->keys[key_index].values );
2389 regval_ctr_init( &data->keys[key_index].values );
2391 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2393 return key_index;
2396 /****************************************************************************
2397 search for a registry key name in the existing printer data
2398 ***************************************************************************/
2400 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2402 int key_index = -1;
2403 int i;
2405 if ( !data || !name )
2406 return -1;
2408 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2410 /* loop over all existing keys */
2412 for ( i=0; i<data->num_keys; i++ ) {
2413 if ( strequal(data->keys[i].name, name) ) {
2414 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2415 key_index = i;
2416 break;
2421 return key_index;
2424 /****************************************************************************
2425 ***************************************************************************/
2427 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2429 int i, j;
2430 int key_len;
2431 int num_subkeys = 0;
2432 char *p;
2433 fstring *ptr, *subkeys_ptr = NULL;
2434 fstring subkeyname;
2436 if ( !data )
2437 return 0;
2439 for ( i=0; i<data->num_keys; i++ ) {
2440 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2441 /* match sure it is a subkey and not the key itself */
2443 key_len = strlen( key );
2444 if ( strlen(data->keys[i].name) == key_len )
2445 continue;
2447 /* get subkey path */
2449 p = data->keys[i].name + key_len;
2450 if ( *p == '\\' )
2451 p++;
2452 fstrcpy( subkeyname, p );
2453 if ( (p = strchr( subkeyname, '\\' )) )
2454 *p = '\0';
2456 /* don't add a key more than once */
2458 for ( j=0; j<num_subkeys; j++ ) {
2459 if ( strequal( subkeys_ptr[j], subkeyname ) )
2460 break;
2463 if ( j != num_subkeys )
2464 continue;
2466 /* found a match, so allocate space and copy the name */
2468 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2469 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2470 num_subkeys+1));
2471 SAFE_FREE( subkeys );
2472 return 0;
2475 subkeys_ptr = ptr;
2476 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2477 num_subkeys++;
2482 /* tag of the end */
2484 if (num_subkeys)
2485 fstrcpy(subkeys_ptr[num_subkeys], "" );
2487 *subkeys = subkeys_ptr;
2489 return num_subkeys;
2492 #ifdef HAVE_ADS
2493 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2494 const char *sz)
2496 smb_ucs2_t conv_str[1024];
2497 size_t str_size;
2499 regval_ctr_delvalue(ctr, val_name);
2500 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2501 STR_TERMINATE | STR_NOALIGN);
2502 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2503 (char *) conv_str, str_size);
2506 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2507 uint32 dword)
2509 regval_ctr_delvalue(ctr, val_name);
2510 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2511 (char *) &dword, sizeof(dword));
2514 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2515 BOOL b)
2517 uint8 bin_bool = (b ? 1 : 0);
2518 regval_ctr_delvalue(ctr, val_name);
2519 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2520 (char *) &bin_bool, sizeof(bin_bool));
2523 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2524 const char *multi_sz)
2526 smb_ucs2_t *conv_strs = NULL;
2527 size_t str_size;
2529 /* a multi-sz has to have a null string terminator, i.e., the last
2530 string must be followed by two nulls */
2531 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2532 conv_strs = calloc(str_size, 1);
2534 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2535 STR_TERMINATE | STR_NOALIGN);
2537 regval_ctr_delvalue(ctr, val_name);
2538 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2539 (char *) conv_strs, str_size);
2540 safe_free(conv_strs);
2544 /****************************************************************************
2545 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2547 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2548 * @return BOOL indicating success or failure
2549 ***************************************************************************/
2551 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2553 REGVAL_CTR *ctr = NULL;
2554 fstring longname;
2555 char *allocated_string = NULL;
2556 const char *ascii_str;
2557 int i;
2559 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2560 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2561 ctr = &info2->data.keys[i].values;
2563 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2564 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2566 get_mydnsfullname(longname);
2567 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2569 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2570 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2571 SAFE_FREE(allocated_string);
2573 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2574 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2575 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2576 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2577 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2578 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2579 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2580 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2581 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2583 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2584 (info2->attributes &
2585 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2587 switch (info2->attributes & 0x3) {
2588 case 0:
2589 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2590 break;
2591 case 1:
2592 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2593 break;
2594 case 2:
2595 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2596 break;
2597 default:
2598 ascii_str = "unknown";
2600 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2602 return True;
2605 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2606 struct uuid guid)
2608 int i;
2609 REGVAL_CTR *ctr=NULL;
2611 /* find the DsSpooler key */
2612 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2613 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2614 ctr = &info2->data.keys[i].values;
2616 regval_ctr_delvalue(ctr, "objectGUID");
2617 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2618 (char *) &guid, sizeof(struct uuid));
2621 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2623 ADS_STATUS ads_rc;
2624 TALLOC_CTX *ctx = talloc_init("publish_it");
2625 ADS_MODLIST mods = ads_init_mods(ctx);
2626 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2627 char *srv_dn_utf8, **srv_cn_utf8;
2628 void *res = NULL;
2629 ADS_STRUCT *ads;
2630 const char *attrs[] = {"objectGUID", NULL};
2631 struct uuid guid;
2632 WERROR win_rc = WERR_OK;
2634 ZERO_STRUCT(guid);
2635 /* set the DsSpooler info and attributes */
2636 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2637 return WERR_NOMEM;
2638 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2639 win_rc = mod_a_printer(*printer, 2);
2640 if (!W_ERROR_IS_OK(win_rc)) {
2641 DEBUG(3, ("err %d saving data\n",
2642 W_ERROR_V(win_rc)));
2643 return win_rc;
2646 /* Build the ads mods */
2647 get_local_printer_publishing_data(ctx, &mods,
2648 &printer->info_2->data);
2649 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2650 printer->info_2->sharename);
2652 /* initial ads structure */
2654 ads = ads_init(NULL, NULL, NULL);
2655 if (!ads) {
2656 DEBUG(3, ("ads_init() failed\n"));
2657 return WERR_SERVER_UNAVAILABLE;
2659 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2660 SAFE_FREE(ads->auth.password);
2661 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2662 NULL, NULL);
2664 /* ads_connect() will find the DC for us */
2665 ads_rc = ads_connect(ads);
2666 if (!ADS_ERR_OK(ads_rc)) {
2667 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2668 ads_destroy(&ads);
2669 return WERR_ACCESS_DENIED;
2672 /* figure out where to publish */
2673 ads_find_machine_acct(ads, &res, global_myname());
2675 /* We use ldap_get_dn here as we need the answer
2676 * in utf8 to call ldap_explode_dn(). JRA. */
2678 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2679 if (!srv_dn_utf8) {
2680 ads_destroy(&ads);
2681 return WERR_SERVER_UNAVAILABLE;
2683 ads_msgfree(ads, res);
2684 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2685 if (!srv_cn_utf8) {
2686 ldap_memfree(srv_dn_utf8);
2687 ads_destroy(&ads);
2688 return WERR_SERVER_UNAVAILABLE;
2690 /* Now convert to CH_UNIX. */
2691 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2692 ldap_memfree(srv_dn_utf8);
2693 ldap_memfree(srv_cn_utf8);
2694 ads_destroy(&ads);
2695 return WERR_SERVER_UNAVAILABLE;
2697 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2698 ldap_memfree(srv_dn_utf8);
2699 ldap_memfree(srv_cn_utf8);
2700 ads_destroy(&ads);
2701 SAFE_FREE(srv_dn);
2702 return WERR_SERVER_UNAVAILABLE;
2705 ldap_memfree(srv_dn_utf8);
2706 ldap_memfree(srv_cn_utf8);
2708 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2709 printer->info_2->sharename, srv_dn);
2711 SAFE_FREE(srv_dn);
2712 SAFE_FREE(srv_cn_0);
2714 /* publish it */
2715 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2716 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2717 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2719 /* retreive the guid and store it locally */
2720 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2721 ads_pull_guid(ads, res, &guid);
2722 ads_msgfree(ads, res);
2723 store_printer_guid(printer->info_2, guid);
2724 win_rc = mod_a_printer(*printer, 2);
2727 SAFE_FREE(prt_dn);
2728 ads_destroy(&ads);
2730 return WERR_OK;
2733 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2735 ADS_STATUS ads_rc;
2736 ADS_STRUCT *ads;
2737 void *res;
2738 char *prt_dn = NULL;
2739 WERROR win_rc;
2741 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2742 win_rc = mod_a_printer(*printer, 2);
2743 if (!W_ERROR_IS_OK(win_rc)) {
2744 DEBUG(3, ("err %d saving data\n",
2745 W_ERROR_V(win_rc)));
2746 return win_rc;
2749 ads = ads_init(NULL, NULL, NULL);
2750 if (!ads) {
2751 DEBUG(3, ("ads_init() failed\n"));
2752 return WERR_SERVER_UNAVAILABLE;
2754 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2755 SAFE_FREE(ads->auth.password);
2756 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2757 NULL, NULL);
2759 /* ads_connect() will find the DC for us */
2760 ads_rc = ads_connect(ads);
2761 if (!ADS_ERR_OK(ads_rc)) {
2762 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2763 ads_destroy(&ads);
2764 return WERR_ACCESS_DENIED;
2767 /* remove the printer from the directory */
2768 ads_rc = ads_find_printer_on_server(ads, &res,
2769 printer->info_2->sharename, global_myname());
2770 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2771 prt_dn = ads_get_dn(ads, res);
2772 ads_msgfree(ads, res);
2773 ads_rc = ads_del_dn(ads, prt_dn);
2774 ads_memfree(ads, prt_dn);
2777 ads_destroy(&ads);
2778 return WERR_OK;
2781 /****************************************************************************
2782 * Publish a printer in the directory
2784 * @param snum describing printer service
2785 * @return WERROR indicating status of publishing
2786 ***************************************************************************/
2788 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2790 NT_PRINTER_INFO_LEVEL *printer = NULL;
2791 WERROR win_rc;
2793 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2794 if (!W_ERROR_IS_OK(win_rc))
2795 return win_rc;
2797 switch(action) {
2798 case SPOOL_DS_PUBLISH:
2799 case SPOOL_DS_UPDATE:
2800 win_rc = publish_it(printer);
2801 break;
2802 case SPOOL_DS_UNPUBLISH:
2803 win_rc = unpublish_it(printer);
2804 break;
2805 default:
2806 win_rc = WERR_NOT_SUPPORTED;
2810 free_a_printer(&printer, 2);
2811 return win_rc;
2814 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2815 struct uuid *guid)
2817 NT_PRINTER_INFO_LEVEL *printer = NULL;
2818 REGVAL_CTR *ctr;
2819 REGISTRY_VALUE *guid_val;
2820 WERROR win_rc;
2821 int i;
2824 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2825 if (!W_ERROR_IS_OK(win_rc))
2826 return False;
2828 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2829 return False;
2831 if ((i = lookup_printerkey(&printer->info_2->data,
2832 SPOOL_DSSPOOLER_KEY)) < 0)
2833 return False;
2835 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2836 return False;
2839 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2840 return False;
2843 if (regval_size(guid_val) == sizeof(struct uuid))
2844 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
2846 return True;
2849 #else
2850 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2852 return WERR_OK;
2854 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2855 struct uuid *guid)
2857 return False;
2859 #endif
2860 /****************************************************************************
2861 ***************************************************************************/
2863 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2865 NT_PRINTER_DATA *data;
2866 int i;
2867 int removed_keys = 0;
2868 int empty_slot;
2870 data = &p2->data;
2871 empty_slot = data->num_keys;
2873 if ( !key )
2874 return WERR_INVALID_PARAM;
2876 /* remove all keys */
2878 if ( !strlen(key) ) {
2879 for ( i=0; i<data->num_keys; i++ ) {
2880 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2881 data->keys[i].name));
2883 SAFE_FREE( data->keys[i].name );
2884 regval_ctr_destroy( &data->keys[i].values );
2887 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2888 p2->printername ));
2890 SAFE_FREE( data->keys );
2891 ZERO_STRUCTP( data );
2893 return WERR_OK;
2896 /* remove a specific key (and all subkeys) */
2898 for ( i=0; i<data->num_keys; i++ ) {
2899 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2900 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2901 data->keys[i].name));
2903 SAFE_FREE( data->keys[i].name );
2904 regval_ctr_destroy( &data->keys[i].values );
2906 /* mark the slot as empty */
2908 ZERO_STRUCTP( &data->keys[i] );
2912 /* find the first empty slot */
2914 for ( i=0; i<data->num_keys; i++ ) {
2915 if ( !data->keys[i].name ) {
2916 empty_slot = i;
2917 removed_keys++;
2918 break;
2922 if ( i == data->num_keys )
2923 /* nothing was removed */
2924 return WERR_INVALID_PARAM;
2926 /* move everything down */
2928 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2929 if ( data->keys[i].name ) {
2930 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2931 ZERO_STRUCTP( &data->keys[i] );
2932 empty_slot++;
2933 removed_keys++;
2937 /* update count */
2939 data->num_keys -= removed_keys;
2941 /* sanity check to see if anything is left */
2943 if ( !data->num_keys ) {
2944 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2946 SAFE_FREE( data->keys );
2947 ZERO_STRUCTP( data );
2950 return WERR_OK;
2953 /****************************************************************************
2954 ***************************************************************************/
2956 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2958 WERROR result = WERR_OK;
2959 int key_index;
2961 /* we must have names on non-zero length */
2963 if ( !key || !*key|| !value || !*value )
2964 return WERR_INVALID_NAME;
2966 /* find the printer key first */
2968 key_index = lookup_printerkey( &p2->data, key );
2969 if ( key_index == -1 )
2970 return WERR_OK;
2972 /* make sure the value exists so we can return the correct error code */
2974 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2975 return WERR_BADFILE;
2977 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2979 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2980 key, value ));
2982 return result;
2985 /****************************************************************************
2986 ***************************************************************************/
2988 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2989 uint32 type, uint8 *data, int real_len )
2991 WERROR result = WERR_OK;
2992 int key_index;
2994 /* we must have names on non-zero length */
2996 if ( !key || !*key|| !value || !*value )
2997 return WERR_INVALID_NAME;
2999 /* find the printer key first */
3001 key_index = lookup_printerkey( &p2->data, key );
3002 if ( key_index == -1 )
3003 key_index = add_new_printer_key( &p2->data, key );
3005 if ( key_index == -1 )
3006 return WERR_NOMEM;
3008 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3009 type, (const char *)data, real_len );
3011 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3012 key, value, type, real_len ));
3014 return result;
3017 /****************************************************************************
3018 ***************************************************************************/
3020 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3022 int key_index;
3024 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3025 return NULL;
3027 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3028 key, value ));
3030 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3033 /****************************************************************************
3034 Unpack a list of registry values frem the TDB
3035 ***************************************************************************/
3037 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3039 int len = 0;
3040 uint32 type;
3041 pstring string, valuename, keyname;
3042 char *str;
3043 int size;
3044 uint8 *data_p;
3045 REGISTRY_VALUE *regval_p;
3046 int key_index;
3048 /* add the "PrinterDriverData" key first for performance reasons */
3050 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3052 /* loop and unpack the rest of the registry values */
3054 while ( True ) {
3056 /* check to see if there are any more registry values */
3058 regval_p = NULL;
3059 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3060 if ( !regval_p )
3061 break;
3063 /* unpack the next regval */
3065 len += tdb_unpack(buf+len, buflen-len, "fdB",
3066 string,
3067 &type,
3068 &size,
3069 &data_p);
3072 * break of the keyname from the value name.
3073 * Should only be one '\' in the string returned.
3076 str = strrchr( string, '\\');
3078 /* Put in "PrinterDriverData" is no key specified */
3080 if ( !str ) {
3081 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3082 pstrcpy( valuename, string );
3084 else {
3085 *str = '\0';
3086 pstrcpy( keyname, string );
3087 pstrcpy( valuename, str+1 );
3090 /* see if we need a new key */
3092 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3093 key_index = add_new_printer_key( printer_data, keyname );
3095 if ( key_index == -1 ) {
3096 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3097 keyname));
3098 break;
3101 /* add the new value */
3103 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3105 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3107 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3110 return len;
3113 /****************************************************************************
3114 ***************************************************************************/
3116 static void map_to_os2_driver(fstring drivername)
3118 static BOOL initialised=False;
3119 static fstring last_from,last_to;
3120 char *mapfile = lp_os2_driver_map();
3121 char **lines = NULL;
3122 int numlines = 0;
3123 int i;
3125 if (!strlen(drivername))
3126 return;
3128 if (!*mapfile)
3129 return;
3131 if (!initialised) {
3132 *last_from = *last_to = 0;
3133 initialised = True;
3136 if (strequal(drivername,last_from)) {
3137 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3138 fstrcpy(drivername,last_to);
3139 return;
3142 lines = file_lines_load(mapfile, &numlines);
3143 if (numlines == 0) {
3144 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3145 return;
3148 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3150 for( i = 0; i < numlines; i++) {
3151 char *nt_name = lines[i];
3152 char *os2_name = strchr(nt_name,'=');
3154 if (!os2_name)
3155 continue;
3157 *os2_name++ = 0;
3159 while (isspace(*nt_name))
3160 nt_name++;
3162 if (!*nt_name || strchr("#;",*nt_name))
3163 continue;
3166 int l = strlen(nt_name);
3167 while (l && isspace(nt_name[l-1])) {
3168 nt_name[l-1] = 0;
3169 l--;
3173 while (isspace(*os2_name))
3174 os2_name++;
3177 int l = strlen(os2_name);
3178 while (l && isspace(os2_name[l-1])) {
3179 os2_name[l-1] = 0;
3180 l--;
3184 if (strequal(nt_name,drivername)) {
3185 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3186 fstrcpy(last_from,drivername);
3187 fstrcpy(last_to,os2_name);
3188 fstrcpy(drivername,os2_name);
3189 file_lines_free(lines);
3190 return;
3194 file_lines_free(lines);
3197 /****************************************************************************
3198 Get a default printer info 2 struct.
3199 ****************************************************************************/
3200 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3202 int snum;
3203 NT_PRINTER_INFO_LEVEL_2 info;
3205 ZERO_STRUCT(info);
3207 snum = lp_servicenumber(sharename);
3209 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3210 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3211 get_called_name(), sharename);
3212 fstrcpy(info.sharename, sharename);
3213 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3215 /* by setting the driver name to an empty string, a local NT admin
3216 can now run the **local** APW to install a local printer driver
3217 for a Samba shared printer in 2.2. Without this, drivers **must** be
3218 installed on the Samba server for NT clients --jerry */
3219 #if 0 /* JERRY --do not uncomment-- */
3220 if (!*info.drivername)
3221 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3222 #endif
3225 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3227 pstrcpy(info.comment, "");
3228 fstrcpy(info.printprocessor, "winprint");
3229 fstrcpy(info.datatype, "RAW");
3231 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3233 info.starttime = 0; /* Minutes since 12:00am GMT */
3234 info.untiltime = 0; /* Minutes since 12:00am GMT */
3235 info.priority = 1;
3236 info.default_priority = 1;
3237 info.setuptime = (uint32)time(NULL);
3240 * I changed this as I think it is better to have a generic
3241 * DEVMODE than to crash Win2k explorer.exe --jerry
3242 * See the HP Deskjet 990c Win2k drivers for an example.
3244 * However the default devmode appears to cause problems
3245 * with the HP CLJ 8500 PCL driver. Hence the addition of
3246 * the "default devmode" parameter --jerry 22/01/2002
3249 if (lp_default_devmode(snum)) {
3250 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3251 goto fail;
3253 else {
3254 info.devmode = NULL;
3257 /* This will get the current RPC talloc context, but we should be
3258 passing this as a parameter... fixme... JRA ! */
3260 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3261 goto fail;
3263 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3264 if (! *info_ptr) {
3265 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3266 goto fail;
3269 return WERR_OK;
3271 fail:
3272 if (info.devmode)
3273 free_nt_devicemode(&info.devmode);
3274 return WERR_ACCESS_DENIED;
3277 /****************************************************************************
3278 ****************************************************************************/
3279 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3281 pstring key;
3282 NT_PRINTER_INFO_LEVEL_2 info;
3283 int len = 0;
3284 TDB_DATA kbuf, dbuf;
3285 fstring printername;
3286 char adevice[MAXDEVICENAME];
3288 ZERO_STRUCT(info);
3290 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3292 kbuf.dptr = key;
3293 kbuf.dsize = strlen(key)+1;
3295 dbuf = tdb_fetch(tdb_printers, kbuf);
3296 if (!dbuf.dptr)
3297 return get_a_printer_2_default(info_ptr, sharename);
3299 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3300 &info.attributes,
3301 &info.priority,
3302 &info.default_priority,
3303 &info.starttime,
3304 &info.untiltime,
3305 &info.status,
3306 &info.cjobs,
3307 &info.averageppm,
3308 &info.changeid,
3309 &info.c_setprinter,
3310 &info.setuptime,
3311 info.servername,
3312 info.printername,
3313 info.sharename,
3314 info.portname,
3315 info.drivername,
3316 info.comment,
3317 info.location,
3318 info.sepfile,
3319 info.printprocessor,
3320 info.datatype,
3321 info.parameters);
3323 /* Samba has to have shared raw drivers. */
3324 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3326 /* Restore the stripped strings. */
3327 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3328 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3329 info.printername);
3330 fstrcpy(info.printername, printername);
3332 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3335 * Some client drivers freak out if there is a NULL devmode
3336 * (probably the driver is not checking before accessing
3337 * the devmode pointer) --jerry
3339 * See comments in get_a_printer_2_default()
3342 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3343 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3344 printername));
3345 info.devmode = construct_nt_devicemode(printername);
3348 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3349 if (info.devmode) {
3350 fstrcpy(info.devmode->devicename, adevice);
3353 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3355 /* This will get the current RPC talloc context, but we should be
3356 passing this as a parameter... fixme... JRA ! */
3358 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3360 /* Fix for OS/2 drivers. */
3362 if (get_remote_arch() == RA_OS2)
3363 map_to_os2_driver(info.drivername);
3365 SAFE_FREE(dbuf.dptr);
3366 *info_ptr=memdup(&info, sizeof(info));
3368 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3369 sharename, info.printername, info.drivername));
3371 return WERR_OK;
3374 /****************************************************************************
3375 Debugging function, dump at level 6 the struct in the logs.
3376 ****************************************************************************/
3377 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3379 uint32 result;
3380 NT_PRINTER_INFO_LEVEL_2 *info2;
3382 DEBUG(106,("Dumping printer at level [%d]\n", level));
3384 switch (level) {
3385 case 2:
3387 if (printer.info_2 == NULL)
3388 result=5;
3389 else
3391 info2=printer.info_2;
3393 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3394 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3395 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3396 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3397 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3398 DEBUGADD(106,("status:[%d]\n", info2->status));
3399 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3400 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3401 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3402 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3403 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3405 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3406 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3407 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3408 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3409 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3410 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3411 DEBUGADD(106,("location:[%s]\n", info2->location));
3412 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3413 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3414 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3415 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3416 result=0;
3418 break;
3420 default:
3421 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3422 result=1;
3423 break;
3426 return result;
3429 /****************************************************************************
3430 Update the changeid time.
3431 This is SO NASTY as some drivers need this to change, others need it
3432 static. This value will change every second, and I must hope that this
3433 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3434 UTAH ! JRA.
3435 ****************************************************************************/
3437 static uint32 rev_changeid(void)
3439 struct timeval tv;
3441 get_process_uptime(&tv);
3443 #if 1 /* JERRY */
3444 /* Return changeid as msec since spooler restart */
3445 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3446 #else
3448 * This setting seems to work well but is too untested
3449 * to replace the above calculation. Left in for experiementation
3450 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3452 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3453 #endif
3457 * The function below are the high level ones.
3458 * only those ones must be called from the spoolss code.
3459 * JFM.
3462 /****************************************************************************
3463 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3464 ****************************************************************************/
3466 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3468 WERROR result;
3470 dump_a_printer(printer, level);
3473 * invalidate cache for all open handles to this printer.
3474 * cache for a given handle will be updated on the next
3475 * get_a_printer()
3478 invalidate_printer_hnd_cache( printer.info_2->sharename );
3480 switch (level) {
3481 case 2:
3484 * Update the changestamp. Emperical tests show that the
3485 * ChangeID is always updated,but c_setprinter is
3486 * global spooler variable (not per printer).
3489 /* ChangeID **must** be increasing over the lifetime
3490 of client's spoolss service in order for the
3491 client's cache to show updates */
3493 printer.info_2->changeid = rev_changeid();
3496 * Because one day someone will ask:
3497 * NT->NT An admin connection to a remote
3498 * printer show changes imeediately in
3499 * the properities dialog
3501 * A non-admin connection will only show the
3502 * changes after viewing the properites page
3503 * 2 times. Seems to be related to a
3504 * race condition in the client between the spooler
3505 * updating the local cache and the Explorer.exe GUI
3506 * actually displaying the properties.
3508 * This is fixed in Win2k. admin/non-admin
3509 * connections both display changes immediately.
3511 * 14/12/01 --jerry
3514 result=update_a_printer_2(printer.info_2);
3516 break;
3518 default:
3519 result=WERR_UNKNOWN_LEVEL;
3520 break;
3523 return result;
3526 /****************************************************************************
3527 Initialize printer devmode & data with previously saved driver init values.
3528 ****************************************************************************/
3530 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3532 int len = 0;
3533 pstring key;
3534 TDB_DATA kbuf, dbuf;
3535 NT_PRINTER_INFO_LEVEL_2 info;
3538 ZERO_STRUCT(info);
3541 * Delete any printer data 'values' already set. When called for driver
3542 * replace, there will generally be some, but during an add printer, there
3543 * should not be any (if there are delete them).
3546 delete_all_printer_data( info_ptr, "" );
3548 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3550 kbuf.dptr = key;
3551 kbuf.dsize = strlen(key)+1;
3553 dbuf = tdb_fetch(tdb_drivers, kbuf);
3554 if (!dbuf.dptr) {
3556 * When changing to a driver that has no init info in the tdb, remove
3557 * the previous drivers init info and leave the new on blank.
3559 free_nt_devicemode(&info_ptr->devmode);
3560 return False;
3564 * Get the saved DEVMODE..
3567 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3570 * The saved DEVMODE contains the devicename from the printer used during
3571 * the initialization save. Change it to reflect the new printer.
3574 if ( info.devmode ) {
3575 ZERO_STRUCT(info.devmode->devicename);
3576 fstrcpy(info.devmode->devicename, info_ptr->printername);
3580 * NT/2k does not change out the entire DeviceMode of a printer
3581 * when changing the driver. Only the driverextra, private, &
3582 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3584 * Later examination revealed that Windows NT/2k does reset the
3585 * the printer's device mode, bit **only** when you change a
3586 * property of the device mode such as the page orientation.
3587 * --jerry
3591 /* Bind the saved DEVMODE to the new the printer */
3593 free_nt_devicemode(&info_ptr->devmode);
3594 info_ptr->devmode = info.devmode;
3596 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3597 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3599 /* Add the printer data 'values' to the new printer */
3601 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3604 SAFE_FREE(dbuf.dptr);
3606 return True;
3609 /****************************************************************************
3610 Initialize printer devmode & data with previously saved driver init values.
3611 When a printer is created using AddPrinter, the drivername bound to the
3612 printer is used to lookup previously saved driver initialization info, which
3613 is bound to the new printer.
3614 ****************************************************************************/
3616 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3618 BOOL result = False;
3620 switch (level) {
3621 case 2:
3622 result = set_driver_init_2(printer->info_2);
3623 break;
3625 default:
3626 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3627 level));
3628 break;
3631 return result;
3634 /****************************************************************************
3635 Delete driver init data stored for a specified driver
3636 ****************************************************************************/
3638 BOOL del_driver_init(char *drivername)
3640 pstring key;
3641 TDB_DATA kbuf;
3643 if (!drivername || !*drivername) {
3644 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3645 return False;
3648 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3650 kbuf.dptr = key;
3651 kbuf.dsize = strlen(key)+1;
3653 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3655 return (tdb_delete(tdb_drivers, kbuf) == 0);
3658 /****************************************************************************
3659 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3660 in the tdb. Note: this is different from the driver entry and the printer
3661 entry. There should be a single driver init entry for each driver regardless
3662 of whether it was installed from NT or 2K. Technically, they should be
3663 different, but they work out to the same struct.
3664 ****************************************************************************/
3666 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3668 pstring key;
3669 char *buf;
3670 int buflen, len, ret;
3671 TDB_DATA kbuf, dbuf;
3673 buf = NULL;
3674 buflen = 0;
3676 again:
3677 len = 0;
3678 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3680 len += pack_values( &info->data, buf+len, buflen-len );
3682 if (buflen != len) {
3683 char *tb;
3685 tb = (char *)Realloc(buf, len);
3686 if (!tb) {
3687 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3688 ret = -1;
3689 goto done;
3691 else
3692 buf = tb;
3693 buflen = len;
3694 goto again;
3697 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3699 kbuf.dptr = key;
3700 kbuf.dsize = strlen(key)+1;
3701 dbuf.dptr = buf;
3702 dbuf.dsize = len;
3704 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3706 done:
3707 if (ret == -1)
3708 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3710 SAFE_FREE(buf);
3712 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3713 info->sharename, info->drivername));
3715 return ret;
3718 /****************************************************************************
3719 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3720 ****************************************************************************/
3722 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3724 uint32 result;
3726 dump_a_printer(printer, level);
3728 switch (level) {
3729 case 2:
3730 result = update_driver_init_2(printer.info_2);
3731 break;
3732 default:
3733 result = 1;
3734 break;
3737 return result;
3740 /****************************************************************************
3741 Convert the printer data value, a REG_BINARY array, into an initialization
3742 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3743 got to keep the endians happy :).
3744 ****************************************************************************/
3746 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3748 BOOL result = False;
3749 prs_struct ps;
3750 DEVICEMODE devmode;
3752 ZERO_STRUCT(devmode);
3754 prs_init(&ps, 0, ctx, UNMARSHALL);
3755 ps.data_p = (char *)data;
3756 ps.buffer_size = data_len;
3758 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3759 result = convert_devicemode("", &devmode, &nt_devmode);
3760 else
3761 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3763 return result;
3766 /****************************************************************************
3767 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3769 1. Use the driver's config DLL to this UNC printername and:
3770 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3771 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3772 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3774 The last step triggers saving the "driver initialization" information for
3775 this printer into the tdb. Later, new printers that use this driver will
3776 have this initialization information bound to them. This simulates the
3777 driver initialization, as if it had run on the Samba server (as it would
3778 have done on NT).
3780 The Win32 client side code requirement sucks! But until we can run arbitrary
3781 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3783 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3784 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3785 about it and you will realize why. JRR 010720
3786 ****************************************************************************/
3788 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3790 WERROR status = WERR_OK;
3791 TALLOC_CTX *ctx = NULL;
3792 NT_DEVICEMODE *nt_devmode = NULL;
3793 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3796 * When the DEVMODE is already set on the printer, don't try to unpack it.
3798 DEBUG(8,("save_driver_init_2: Enter...\n"));
3800 if ( !printer->info_2->devmode && data_len ) {
3802 * Set devmode on printer info, so entire printer initialization can be
3803 * saved to tdb.
3806 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3807 return WERR_NOMEM;
3809 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3810 status = WERR_NOMEM;
3811 goto done;
3814 ZERO_STRUCTP(nt_devmode);
3817 * The DEVMODE is held in the 'data' component of the param in raw binary.
3818 * Convert it to to a devmode structure
3820 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3821 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3822 status = WERR_INVALID_PARAM;
3823 goto done;
3826 printer->info_2->devmode = nt_devmode;
3830 * Pack up and add (or update) the DEVMODE and any current printer data to
3831 * a 'driver init' element in the tdb
3835 if ( update_driver_init(*printer, 2) != 0 ) {
3836 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3837 status = WERR_NOMEM;
3838 goto done;
3842 * If driver initialization info was successfully saved, set the current
3843 * printer to match it. This allows initialization of the current printer
3844 * as well as the driver.
3846 status = mod_a_printer(*printer, 2);
3847 if (!W_ERROR_IS_OK(status)) {
3848 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3849 printer->info_2->printername));
3852 done:
3853 talloc_destroy(ctx);
3854 free_nt_devicemode( &nt_devmode );
3856 printer->info_2->devmode = tmp_devmode;
3858 return status;
3861 /****************************************************************************
3862 Update the driver init info (DEVMODE and specifics) for a printer
3863 ****************************************************************************/
3865 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3867 WERROR status = WERR_OK;
3869 switch (level) {
3870 case 2:
3871 status = save_driver_init_2( printer, data, data_len );
3872 break;
3873 default:
3874 status = WERR_UNKNOWN_LEVEL;
3875 break;
3878 return status;
3881 /****************************************************************************
3882 Deep copy a NT_PRINTER_DATA
3883 ****************************************************************************/
3885 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3887 int i, j, num_vals, new_key_index;
3888 REGVAL_CTR *src_key, *dst_key;
3890 if ( !dst || !src )
3891 return NT_STATUS_NO_MEMORY;
3893 for ( i=0; i<src->num_keys; i++ ) {
3895 /* create a new instance of the printerkey in the destination
3896 printer_data object */
3898 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3899 dst_key = &dst->keys[new_key_index].values;
3901 src_key = &src->keys[i].values;
3902 num_vals = regval_ctr_numvals( src_key );
3904 /* dup the printer entire printer key */
3906 for ( j=0; j<num_vals; j++ ) {
3907 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3911 return NT_STATUS_OK;
3914 /****************************************************************************
3915 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3916 Caller must free.
3917 ****************************************************************************/
3919 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3921 NT_PRINTER_INFO_LEVEL_2 *copy;
3923 if ( !printer )
3924 return NULL;
3926 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3927 return NULL;
3929 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3931 /* malloc()'d members copied here */
3933 copy->devmode = dup_nt_devicemode( printer->devmode );
3935 ZERO_STRUCT( copy->data );
3936 copy_printer_data( &copy->data, &printer->data );
3938 /* this is talloc()'d; very ugly that we have a structure that
3939 is half malloc()'d and half talloc()'d but that is the way
3940 that the PRINTER_INFO stuff is written right now. --jerry */
3942 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3944 return copy;
3947 /****************************************************************************
3948 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3950 Previously the code had a memory allocation problem because it always
3951 used the TALLOC_CTX from the Printer_entry*. This context lasts
3952 as a long as the original handle is open. So if the client made a lot
3953 of getprinter[data]() calls, the memory usage would climb. Now we use
3954 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3955 still use the Printer_entry->ctx for maintaining the cache copy though
3956 since that object must live as long as the handle by definition.
3957 --jerry
3959 ****************************************************************************/
3961 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3962 const char *sharename)
3964 WERROR result;
3965 NT_PRINTER_INFO_LEVEL *printer = NULL;
3967 *pp_printer = NULL;
3969 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3971 switch (level) {
3972 case 2:
3973 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3974 DEBUG(0,("get_a_printer: malloc fail.\n"));
3975 return WERR_NOMEM;
3977 ZERO_STRUCTP(printer);
3980 * check for cache first. A Printer handle cannot changed
3981 * to another printer object so we only check that the printer
3982 * is actually for a printer and that the printer_info pointer
3983 * is valid
3985 if ( print_hnd
3986 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3987 && print_hnd->printer_info )
3989 /* get_talloc_ctx() works here because we need a short
3990 lived talloc context */
3992 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
3994 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3996 SAFE_FREE(printer);
3997 return WERR_NOMEM;
4000 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4002 *pp_printer = printer;
4003 result = WERR_OK;
4005 break;
4008 /* no cache for this handle; see if we can match one from another handle.
4009 Make sure to use a short lived talloc ctx */
4011 if ( print_hnd )
4012 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, sharename);
4014 /* fail to disk if we don't have it with any open handle */
4016 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4017 result = get_a_printer_2(&printer->info_2, sharename);
4019 /* we have a new printer now. Save it with this handle */
4021 if ( W_ERROR_IS_OK(result) ) {
4022 dump_a_printer(*printer, level);
4024 /* save a copy in cache */
4025 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4026 if ( !print_hnd->printer_info )
4027 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
4029 if ( print_hnd->printer_info ) {
4030 /* make sure to use the handle's talloc ctx here since
4031 the printer_2 object must last until the handle is closed */
4033 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4035 /* don't fail the lookup just because the cache update failed */
4036 if ( !print_hnd->printer_info->info_2 )
4037 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4040 *pp_printer = printer;
4042 else
4043 SAFE_FREE(printer);
4045 break;
4047 default:
4048 result=WERR_UNKNOWN_LEVEL;
4049 break;
4052 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4054 return result;
4057 /****************************************************************************
4058 Deletes a NT_PRINTER_INFO_LEVEL struct.
4059 ****************************************************************************/
4061 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4063 uint32 result;
4064 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4066 DEBUG(104,("freeing a printer at level [%d]\n", level));
4068 if (printer == NULL)
4069 return 0;
4071 switch (level) {
4072 case 2:
4073 if (printer->info_2 != NULL) {
4074 free_nt_printer_info_level_2(&printer->info_2);
4075 result=0;
4076 } else
4077 result=4;
4078 break;
4080 default:
4081 result=1;
4082 break;
4085 SAFE_FREE(*pp_printer);
4086 return result;
4089 /****************************************************************************
4090 ****************************************************************************/
4091 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4093 uint32 result;
4094 DEBUG(104,("adding a printer at level [%d]\n", level));
4095 dump_a_printer_driver(driver, level);
4097 switch (level) {
4098 case 3:
4099 result=add_a_printer_driver_3(driver.info_3);
4100 break;
4102 case 6:
4103 result=add_a_printer_driver_6(driver.info_6);
4104 break;
4106 default:
4107 result=1;
4108 break;
4111 return result;
4113 /****************************************************************************
4114 ****************************************************************************/
4116 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4117 fstring drivername, const char *architecture, uint32 version)
4119 WERROR result;
4121 switch (level) {
4122 case 3:
4123 /* Sometime we just want any version of the driver */
4125 if ( version == DRIVER_ANY_VERSION ) {
4126 /* look for Win2k first and then for NT4 */
4127 result = get_a_printer_driver_3(&driver->info_3, drivername,
4128 architecture, 3);
4130 if ( !W_ERROR_IS_OK(result) ) {
4131 result = get_a_printer_driver_3( &driver->info_3,
4132 drivername, architecture, 2 );
4134 } else {
4135 result = get_a_printer_driver_3(&driver->info_3, drivername,
4136 architecture, version);
4138 break;
4140 default:
4141 result=W_ERROR(1);
4142 break;
4145 if (W_ERROR_IS_OK(result))
4146 dump_a_printer_driver(*driver, level);
4148 return result;
4151 /****************************************************************************
4152 ****************************************************************************/
4153 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4155 uint32 result;
4157 switch (level) {
4158 case 3:
4160 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4161 if (driver.info_3 != NULL)
4163 info3=driver.info_3;
4164 SAFE_FREE(info3->dependentfiles);
4165 ZERO_STRUCTP(info3);
4166 SAFE_FREE(info3);
4167 result=0;
4168 } else {
4169 result=4;
4171 break;
4173 case 6:
4175 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4176 if (driver.info_6 != NULL) {
4177 info6=driver.info_6;
4178 SAFE_FREE(info6->dependentfiles);
4179 SAFE_FREE(info6->previousnames);
4180 ZERO_STRUCTP(info6);
4181 SAFE_FREE(info6);
4182 result=0;
4183 } else {
4184 result=4;
4186 break;
4188 default:
4189 result=1;
4190 break;
4192 return result;
4196 /****************************************************************************
4197 Determine whether or not a particular driver is currently assigned
4198 to a printer
4199 ****************************************************************************/
4201 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4203 int snum;
4204 int n_services = lp_numservices();
4205 NT_PRINTER_INFO_LEVEL *printer = NULL;
4207 if ( !info_3 )
4208 return False;
4210 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4212 /* loop through the printers.tdb and check for the drivername */
4214 for (snum=0; snum<n_services; snum++) {
4215 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4216 continue;
4218 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4219 continue;
4221 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4222 free_a_printer( &printer, 2 );
4223 return True;
4226 free_a_printer( &printer, 2 );
4229 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4231 /* report that the driver is not in use by default */
4233 return False;
4237 /**********************************************************************
4238 Check to see if a ogiven file is in use by *info
4239 *********************************************************************/
4241 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4243 int i = 0;
4245 if ( !info )
4246 return False;
4248 if ( strequal(file, info->driverpath) )
4249 return True;
4251 if ( strequal(file, info->datafile) )
4252 return True;
4254 if ( strequal(file, info->configfile) )
4255 return True;
4257 if ( strequal(file, info->helpfile) )
4258 return True;
4260 /* see of there are any dependent files to examine */
4262 if ( !info->dependentfiles )
4263 return False;
4265 while ( *info->dependentfiles[i] ) {
4266 if ( strequal(file, info->dependentfiles[i]) )
4267 return True;
4268 i++;
4271 return False;
4275 /**********************************************************************
4276 Utility function to remove the dependent file pointed to by the
4277 input parameter from the list
4278 *********************************************************************/
4280 static void trim_dependent_file( fstring files[], int idx )
4283 /* bump everything down a slot */
4285 while( *files[idx+1] ) {
4286 fstrcpy( files[idx], files[idx+1] );
4287 idx++;
4290 *files[idx] = '\0';
4292 return;
4295 /**********************************************************************
4296 Check if any of the files used by src are also used by drv
4297 *********************************************************************/
4299 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4300 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4302 BOOL in_use = False;
4303 int i = 0;
4305 if ( !src || !drv )
4306 return False;
4308 /* check each file. Remove it from the src structure if it overlaps */
4310 if ( drv_file_in_use(src->driverpath, drv) ) {
4311 in_use = True;
4312 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4313 fstrcpy( src->driverpath, "" );
4316 if ( drv_file_in_use(src->datafile, drv) ) {
4317 in_use = True;
4318 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4319 fstrcpy( src->datafile, "" );
4322 if ( drv_file_in_use(src->configfile, drv) ) {
4323 in_use = True;
4324 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4325 fstrcpy( src->configfile, "" );
4328 if ( drv_file_in_use(src->helpfile, drv) ) {
4329 in_use = True;
4330 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4331 fstrcpy( src->helpfile, "" );
4334 /* are there any dependentfiles to examine? */
4336 if ( !src->dependentfiles )
4337 return in_use;
4339 while ( *src->dependentfiles[i] ) {
4340 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4341 in_use = True;
4342 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4343 trim_dependent_file( src->dependentfiles, i );
4344 } else
4345 i++;
4348 return in_use;
4351 /****************************************************************************
4352 Determine whether or not a particular driver files are currently being
4353 used by any other driver.
4355 Return value is True if any files were in use by other drivers
4356 and False otherwise.
4358 Upon return, *info has been modified to only contain the driver files
4359 which are not in use
4360 ****************************************************************************/
4362 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4364 int i;
4365 int ndrivers;
4366 uint32 version;
4367 fstring *list = NULL;
4368 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4370 if ( !info )
4371 return False;
4373 version = info->cversion;
4375 /* loop over all driver versions */
4377 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4379 /* get the list of drivers */
4381 list = NULL;
4382 ndrivers = get_ntdrivers(&list, info->environment, version);
4384 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4385 ndrivers, info->environment, version));
4387 /* check each driver for overlap in files */
4389 for (i=0; i<ndrivers; i++) {
4390 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4392 ZERO_STRUCT(driver);
4394 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4395 SAFE_FREE(list);
4396 return True;
4399 /* check if d2 uses any files from d1 */
4400 /* only if this is a different driver than the one being deleted */
4402 if ( !strequal(info->name, driver.info_3->name) ) {
4403 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4404 free_a_printer_driver(driver, 3);
4405 SAFE_FREE( list );
4406 return True;
4410 free_a_printer_driver(driver, 3);
4413 SAFE_FREE(list);
4415 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4417 driver.info_3 = info;
4419 if ( DEBUGLEVEL >= 20 )
4420 dump_a_printer_driver( driver, 3 );
4422 return False;
4425 /****************************************************************************
4426 Actually delete the driver files. Make sure that
4427 printer_driver_files_in_use() return False before calling
4428 this.
4429 ****************************************************************************/
4431 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4433 int i = 0;
4434 char *s;
4435 connection_struct *conn;
4436 DATA_BLOB null_pw;
4437 NTSTATUS nt_status;
4438 fstring res_type;
4439 BOOL bad_path;
4440 SMB_STRUCT_STAT st;
4442 if ( !info_3 )
4443 return False;
4445 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4448 * Connect to the print$ share under the same account as the
4449 * user connected to the rpc pipe. Note we must be root to
4450 * do this.
4453 null_pw = data_blob( NULL, 0 );
4454 fstrcpy(res_type, "A:");
4455 become_root();
4456 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4457 unbecome_root();
4459 if ( !conn ) {
4460 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4461 return False;
4464 /* Save who we are - we are temporarily becoming the connection user. */
4466 if ( !become_user(conn, conn->vuid) ) {
4467 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4468 return False;
4471 /* now delete the files; must strip the '\print$' string from
4472 fron of path */
4474 if ( *info_3->driverpath ) {
4475 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4476 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4477 DEBUG(10,("deleting driverfile [%s]\n", s));
4478 unlink_internals(conn, 0, s);
4482 if ( *info_3->configfile ) {
4483 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4484 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4485 DEBUG(10,("deleting configfile [%s]\n", s));
4486 unlink_internals(conn, 0, s);
4490 if ( *info_3->datafile ) {
4491 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4492 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4493 DEBUG(10,("deleting datafile [%s]\n", s));
4494 unlink_internals(conn, 0, s);
4498 if ( *info_3->helpfile ) {
4499 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4500 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4501 DEBUG(10,("deleting helpfile [%s]\n", s));
4502 unlink_internals(conn, 0, s);
4506 /* check if we are done removing files */
4508 if ( info_3->dependentfiles ) {
4509 while ( *info_3->dependentfiles[i] ) {
4510 char *file;
4512 /* bypass the "\print$" portion of the path */
4514 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4515 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4516 DEBUG(10,("deleting dependent file [%s]\n", file));
4517 unlink_internals(conn, 0, file );
4520 i++;
4524 unbecome_user();
4526 return True;
4529 /****************************************************************************
4530 Remove a printer driver from the TDB. This assumes that the the driver was
4531 previously looked up.
4532 ***************************************************************************/
4534 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4535 uint32 version, BOOL delete_files )
4537 pstring key;
4538 const char *arch;
4539 TDB_DATA kbuf, dbuf;
4540 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4542 /* delete the tdb data first */
4544 arch = get_short_archi(info_3->environment);
4545 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4546 arch, version, info_3->name);
4548 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4549 key, delete_files ? "TRUE" : "FALSE" ));
4551 ctr.info_3 = info_3;
4552 dump_a_printer_driver( ctr, 3 );
4554 kbuf.dptr=key;
4555 kbuf.dsize=strlen(key)+1;
4557 /* check if the driver actually exists for this environment */
4559 dbuf = tdb_fetch( tdb_drivers, kbuf );
4560 if ( !dbuf.dptr ) {
4561 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4562 return WERR_UNKNOWN_PRINTER_DRIVER;
4565 SAFE_FREE( dbuf.dptr );
4567 /* ok... the driver exists so the delete should return success */
4569 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4570 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4571 return WERR_ACCESS_DENIED;
4575 * now delete any associated files if delete_files == True
4576 * even if this part failes, we return succes because the
4577 * driver doesn not exist any more
4580 if ( delete_files )
4581 delete_driver_files( info_3, user );
4584 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4586 return WERR_OK;
4589 /****************************************************************************
4590 Store a security desc for a printer.
4591 ****************************************************************************/
4593 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4595 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4596 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4597 prs_struct ps;
4598 TALLOC_CTX *mem_ctx = NULL;
4599 fstring key;
4600 WERROR status;
4602 mem_ctx = talloc_init("nt_printing_setsec");
4603 if (mem_ctx == NULL)
4604 return WERR_NOMEM;
4606 /* The old owner and group sids of the security descriptor are not
4607 present when new ACEs are added or removed by changing printer
4608 permissions through NT. If they are NULL in the new security
4609 descriptor then copy them over from the old one. */
4611 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4612 DOM_SID *owner_sid, *group_sid;
4613 SEC_ACL *dacl, *sacl;
4614 SEC_DESC *psd = NULL;
4615 size_t size;
4617 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4619 /* Pick out correct owner and group sids */
4621 owner_sid = secdesc_ctr->sec->owner_sid ?
4622 secdesc_ctr->sec->owner_sid :
4623 old_secdesc_ctr->sec->owner_sid;
4625 group_sid = secdesc_ctr->sec->grp_sid ?
4626 secdesc_ctr->sec->grp_sid :
4627 old_secdesc_ctr->sec->grp_sid;
4629 dacl = secdesc_ctr->sec->dacl ?
4630 secdesc_ctr->sec->dacl :
4631 old_secdesc_ctr->sec->dacl;
4633 sacl = secdesc_ctr->sec->sacl ?
4634 secdesc_ctr->sec->sacl :
4635 old_secdesc_ctr->sec->sacl;
4637 /* Make a deep copy of the security descriptor */
4639 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4640 owner_sid, group_sid,
4641 sacl,
4642 dacl,
4643 &size);
4645 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4648 if (!new_secdesc_ctr) {
4649 new_secdesc_ctr = secdesc_ctr;
4652 /* Store the security descriptor in a tdb */
4654 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4655 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4657 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4658 &ps, 1)) {
4659 status = WERR_BADFUNC;
4660 goto out;
4663 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4665 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4666 status = WERR_OK;
4667 } else {
4668 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4669 status = WERR_BADFUNC;
4672 /* Free malloc'ed memory */
4674 out:
4676 prs_mem_free(&ps);
4677 if (mem_ctx)
4678 talloc_destroy(mem_ctx);
4679 return status;
4682 /****************************************************************************
4683 Construct a default security descriptor buffer for a printer.
4684 ****************************************************************************/
4686 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4688 SEC_ACE ace[3];
4689 SEC_ACCESS sa;
4690 SEC_ACL *psa = NULL;
4691 SEC_DESC_BUF *sdb = NULL;
4692 SEC_DESC *psd = NULL;
4693 DOM_SID owner_sid;
4694 size_t sd_size;
4696 /* Create an ACE where Everyone is allowed to print */
4698 init_sec_access(&sa, PRINTER_ACE_PRINT);
4699 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4700 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4702 /* Make the security descriptor owned by the Administrators group
4703 on the PDC of the domain. */
4705 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4706 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4707 } else {
4709 /* Backup plan - make printer owned by admins.
4710 This should emulate a lanman printer as security
4711 settings can't be changed. */
4713 sid_copy(&owner_sid, get_global_sam_sid());
4714 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4717 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4718 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4719 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4720 SEC_ACE_FLAG_INHERIT_ONLY);
4722 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4723 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4724 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4726 /* The ACL revision number in rpc_secdesc.h differs from the one
4727 created by NT when setting ACE entries in printer
4728 descriptors. NT4 complains about the property being edited by a
4729 NT5 machine. */
4731 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4732 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4733 &owner_sid, NULL,
4734 NULL, psa, &sd_size);
4737 if (!psd) {
4738 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4739 return NULL;
4742 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4744 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4745 (unsigned int)sd_size));
4747 return sdb;
4750 /****************************************************************************
4751 Get a security desc for a printer.
4752 ****************************************************************************/
4754 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4756 prs_struct ps;
4757 fstring key;
4758 char *temp;
4760 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4761 printername = temp + 1;
4764 /* Fetch security descriptor from tdb */
4766 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4768 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4769 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4771 DEBUG(4,("using default secdesc for %s\n", printername));
4773 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4774 return False;
4777 /* Save default security descriptor for later */
4779 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4780 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4782 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4783 tdb_prs_store(tdb_printers, key, &ps);
4785 prs_mem_free(&ps);
4787 return True;
4790 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4791 this security descriptor has been created when winbindd was
4792 down. Take ownership of security descriptor. */
4794 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4795 DOM_SID owner_sid;
4797 /* Change sd owner to workgroup administrator */
4799 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4800 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4801 SEC_DESC *psd = NULL;
4802 size_t size;
4804 /* Create new sd */
4806 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4808 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4809 &owner_sid,
4810 (*secdesc_ctr)->sec->grp_sid,
4811 (*secdesc_ctr)->sec->sacl,
4812 (*secdesc_ctr)->sec->dacl,
4813 &size);
4815 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4817 /* Swap with other one */
4819 *secdesc_ctr = new_secdesc_ctr;
4821 /* Set it */
4823 nt_printing_setsec(printername, *secdesc_ctr);
4827 if (DEBUGLEVEL >= 10) {
4828 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4829 int i;
4831 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4832 printername, the_acl->num_aces));
4834 for (i = 0; i < the_acl->num_aces; i++) {
4835 fstring sid_str;
4837 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4839 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4840 the_acl->ace[i].type, the_acl->ace[i].flags,
4841 the_acl->ace[i].info.mask));
4845 prs_mem_free(&ps);
4846 return True;
4849 /* error code:
4850 0: everything OK
4851 1: level not implemented
4852 2: file doesn't exist
4853 3: can't allocate memory
4854 4: can't free memory
4855 5: non existant struct
4859 A printer and a printer driver are 2 different things.
4860 NT manages them separatelly, Samba does the same.
4861 Why ? Simply because it's easier and it makes sense !
4863 Now explanation: You have 3 printers behind your samba server,
4864 2 of them are the same make and model (laser A and B). But laser B
4865 has an 3000 sheet feeder and laser A doesn't such an option.
4866 Your third printer is an old dot-matrix model for the accounting :-).
4868 If the /usr/local/samba/lib directory (default dir), you will have
4869 5 files to describe all of this.
4871 3 files for the printers (1 by printer):
4872 NTprinter_laser A
4873 NTprinter_laser B
4874 NTprinter_accounting
4875 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4876 NTdriver_printer model X
4877 NTdriver_printer model Y
4879 jfm: I should use this comment for the text file to explain
4880 same thing for the forms BTW.
4881 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4885 /* Convert generic access rights to printer object specific access rights.
4886 It turns out that NT4 security descriptors use generic access rights and
4887 NT5 the object specific ones. */
4889 void map_printer_permissions(SEC_DESC *sd)
4891 int i;
4893 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4894 se_map_generic(&sd->dacl->ace[i].info.mask,
4895 &printer_generic_mapping);
4899 /****************************************************************************
4900 Check a user has permissions to perform the given operation. We use the
4901 permission constants defined in include/rpc_spoolss.h to check the various
4902 actions we perform when checking printer access.
4904 PRINTER_ACCESS_ADMINISTER:
4905 print_queue_pause, print_queue_resume, update_printer_sec,
4906 update_printer, spoolss_addprinterex_level_2,
4907 _spoolss_setprinterdata
4909 PRINTER_ACCESS_USE:
4910 print_job_start
4912 JOB_ACCESS_ADMINISTER:
4913 print_job_delete, print_job_pause, print_job_resume,
4914 print_queue_purge
4916 ****************************************************************************/
4917 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4919 SEC_DESC_BUF *secdesc = NULL;
4920 uint32 access_granted;
4921 NTSTATUS status;
4922 BOOL result;
4923 const char *pname;
4924 TALLOC_CTX *mem_ctx = NULL;
4925 extern struct current_user current_user;
4927 /* If user is NULL then use the current_user structure */
4929 if (!user)
4930 user = &current_user;
4932 /* Always allow root or printer admins to do anything */
4934 if (user->uid == 0 ||
4935 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4936 return True;
4939 /* Get printer name */
4941 pname = PRINTERNAME(snum);
4943 if (!pname || !*pname) {
4944 errno = EACCES;
4945 return False;
4948 /* Get printer security descriptor */
4950 if(!(mem_ctx = talloc_init("print_access_check"))) {
4951 errno = ENOMEM;
4952 return False;
4955 nt_printing_getsec(mem_ctx, pname, &secdesc);
4957 if (access_type == JOB_ACCESS_ADMINISTER) {
4958 SEC_DESC_BUF *parent_secdesc = secdesc;
4960 /* Create a child security descriptor to check permissions
4961 against. This is because print jobs are child objects
4962 objects of a printer. */
4964 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4966 /* Now this is the bit that really confuses me. The access
4967 type needs to be changed from JOB_ACCESS_ADMINISTER to
4968 PRINTER_ACCESS_ADMINISTER for this to work. Something
4969 to do with the child (job) object becoming like a
4970 printer?? -tpot */
4972 access_type = PRINTER_ACCESS_ADMINISTER;
4975 /* Check access */
4977 map_printer_permissions(secdesc->sec);
4979 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4980 &access_granted, &status);
4982 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4984 talloc_destroy(mem_ctx);
4986 if (!result)
4987 errno = EACCES;
4989 return result;
4992 /****************************************************************************
4993 Check the time parameters allow a print operation.
4994 *****************************************************************************/
4996 BOOL print_time_access_check(int snum)
4998 NT_PRINTER_INFO_LEVEL *printer = NULL;
4999 BOOL ok = False;
5000 time_t now = time(NULL);
5001 struct tm *t;
5002 uint32 mins;
5004 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5005 return False;
5007 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5008 ok = True;
5010 t = gmtime(&now);
5011 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5013 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5014 ok = True;
5016 free_a_printer(&printer, 2);
5018 if (!ok)
5019 errno = EACCES;
5021 return ok;