r3727: Update from Rob Foehl (rwf@loonybin.net):
[Samba/nascimento.git] / source3 / printing / nt_printing.c
blob2dc565c79c6b2488cbab7ae34f4c216eaef17c3d
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"
212 #define SPL_ARCH_IA64 "IA64"
213 #define SPL_ARCH_X64 "x64"
215 static const struct table_node archi_table[]= {
217 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
218 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
219 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
220 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
221 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
222 {"Windows IA64", SPL_ARCH_IA64, 3 },
223 {"Windows x64", SPL_ARCH_X64, 3 },
224 {NULL, "", -1 }
227 static BOOL upgrade_to_version_3(void)
229 TDB_DATA kbuf, newkey, dbuf;
231 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
233 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
234 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
236 dbuf = tdb_fetch(tdb_drivers, kbuf);
238 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
239 DEBUG(0,("upgrade_to_version_3:moving form\n"));
240 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
241 SAFE_FREE(dbuf.dptr);
242 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
243 return False;
245 if (tdb_delete(tdb_drivers, kbuf) != 0) {
246 SAFE_FREE(dbuf.dptr);
247 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
248 return False;
252 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
253 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
254 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
255 SAFE_FREE(dbuf.dptr);
256 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
257 return False;
259 if (tdb_delete(tdb_drivers, kbuf) != 0) {
260 SAFE_FREE(dbuf.dptr);
261 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
262 return False;
266 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
267 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
268 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
269 SAFE_FREE(dbuf.dptr);
270 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
271 return False;
273 if (tdb_delete(tdb_drivers, kbuf) != 0) {
274 SAFE_FREE(dbuf.dptr);
275 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
276 return False;
280 SAFE_FREE(dbuf.dptr);
283 return True;
286 /****************************************************************************
287 Open the NT printing tdbs. Done once before fork().
288 ****************************************************************************/
290 BOOL nt_printing_init(void)
292 static pid_t local_pid;
293 const char *vstring = "INFO/version";
294 WERROR win_rc;
296 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
297 return True;
299 if (tdb_drivers)
300 tdb_close(tdb_drivers);
301 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
302 if (!tdb_drivers) {
303 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
304 lock_path("ntdrivers.tdb"), strerror(errno) ));
305 return False;
308 if (tdb_printers)
309 tdb_close(tdb_printers);
310 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
311 if (!tdb_printers) {
312 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
313 lock_path("ntprinters.tdb"), strerror(errno) ));
314 return False;
317 if (tdb_forms)
318 tdb_close(tdb_forms);
319 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
320 if (!tdb_forms) {
321 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
322 lock_path("ntforms.tdb"), strerror(errno) ));
323 return False;
326 local_pid = sys_getpid();
328 /* handle a Samba upgrade */
329 tdb_lock_bystring(tdb_drivers, vstring, 0);
331 int32 vers_id;
333 /* Cope with byte-reversed older versions of the db. */
334 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
335 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
336 /* Written on a bigendian machine with old fetch_int code. Save as le. */
337 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
338 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
339 vers_id = NTDRIVERS_DATABASE_VERSION;
342 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
344 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
345 if (!upgrade_to_version_3())
346 return False;
347 } else
348 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
350 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
353 tdb_unlock_bystring(tdb_drivers, vstring);
355 update_c_setprinter(True);
358 * register callback to handle updating printers as new
359 * drivers are installed
362 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
365 * register callback to handle updating printer data
366 * when a driver is initialized
369 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
372 * register callback to handle invalidating the printer cache
373 * between smbd processes.
376 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
378 /* of course, none of the message callbacks matter if you don't
379 tell messages.c that you interested in receiving PRINT_GENERAL
380 msgs. This is done in claim_connection() */
383 if ( lp_security() == SEC_ADS ) {
384 win_rc = check_published_printers();
385 if (!W_ERROR_IS_OK(win_rc))
386 DEBUG(0, ("nt_printing_init: error checking published printers: %s\n", dos_errstr(win_rc)));
389 return True;
392 /*******************************************************************
393 Function to allow filename parsing "the old way".
394 ********************************************************************/
396 static BOOL driver_unix_convert(char *name,connection_struct *conn,
397 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
399 unix_format(name);
400 unix_clean_name(name);
401 trim_string(name,"/","/");
402 return unix_convert(name, conn, saved_last_component, bad_path, pst);
405 /*******************************************************************
406 tdb traversal function for counting printers.
407 ********************************************************************/
409 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
410 TDB_DATA data, void *context)
412 int *printer_count = (int*)context;
414 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
415 (*printer_count)++;
416 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
419 return 0;
422 /*******************************************************************
423 Update the spooler global c_setprinter. This variable is initialized
424 when the parent smbd starts with the number of existing printers. It
425 is monotonically increased by the current number of printers *after*
426 each add or delete printer RPC. Only Microsoft knows why... JRR020119
427 ********************************************************************/
429 uint32 update_c_setprinter(BOOL initialize)
431 int32 c_setprinter;
432 int32 printer_count = 0;
434 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
436 /* Traverse the tdb, counting the printers */
437 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
439 /* If initializing, set c_setprinter to current printers count
440 * otherwise, bump it by the current printer count
442 if (!initialize)
443 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
444 else
445 c_setprinter = printer_count;
447 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
448 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
450 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
452 return (uint32)c_setprinter;
455 /*******************************************************************
456 Get the spooler global c_setprinter, accounting for initialization.
457 ********************************************************************/
459 uint32 get_c_setprinter(void)
461 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
463 if (c_setprinter == (int32)-1)
464 c_setprinter = update_c_setprinter(True);
466 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
468 return (uint32)c_setprinter;
471 /****************************************************************************
472 Get builtin form struct list.
473 ****************************************************************************/
475 int get_builtin_ntforms(nt_forms_struct **list)
477 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
478 return sizeof(default_forms) / sizeof(default_forms[0]);
481 /****************************************************************************
482 get a builtin form struct
483 ****************************************************************************/
485 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
487 int i,count;
488 fstring form_name;
489 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
490 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
491 count = sizeof(default_forms) / sizeof(default_forms[0]);
492 for (i=0;i<count;i++) {
493 if (strequal(form_name,default_forms[i].name)) {
494 DEBUGADD(6,("Found builtin form %s \n", form_name));
495 memcpy(form,&default_forms[i],sizeof(*form));
496 break;
500 return (i !=count);
503 /****************************************************************************
504 get a form struct list
505 ****************************************************************************/
506 int get_ntforms(nt_forms_struct **list)
508 TDB_DATA kbuf, newkey, dbuf;
509 nt_forms_struct *tl;
510 nt_forms_struct form;
511 int ret;
512 int i;
513 int n = 0;
515 for (kbuf = tdb_firstkey(tdb_forms);
516 kbuf.dptr;
517 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
519 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
520 continue;
522 dbuf = tdb_fetch(tdb_forms, kbuf);
523 if (!dbuf.dptr)
524 continue;
526 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
527 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
528 &i, &form.flag, &form.width, &form.length, &form.left,
529 &form.top, &form.right, &form.bottom);
530 SAFE_FREE(dbuf.dptr);
531 if (ret != dbuf.dsize)
532 continue;
534 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
535 if (!tl) {
536 DEBUG(0,("get_ntforms: Realloc fail.\n"));
537 return 0;
539 *list = tl;
540 (*list)[n] = form;
541 n++;
545 return n;
548 /****************************************************************************
549 write a form struct list
550 ****************************************************************************/
551 int write_ntforms(nt_forms_struct **list, int number)
553 pstring buf, key;
554 int len;
555 TDB_DATA kbuf,dbuf;
556 int i;
558 for (i=0;i<number;i++) {
559 /* save index, so list is rebuilt in correct order */
560 len = tdb_pack(buf, sizeof(buf), "dddddddd",
561 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
562 (*list)[i].left, (*list)[i].top, (*list)[i].right,
563 (*list)[i].bottom);
564 if (len > sizeof(buf)) break;
565 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
566 kbuf.dsize = strlen(key)+1;
567 kbuf.dptr = key;
568 dbuf.dsize = len;
569 dbuf.dptr = buf;
570 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
573 return i;
576 /****************************************************************************
577 add a form struct at the end of the list
578 ****************************************************************************/
579 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
581 int n=0;
582 BOOL update;
583 fstring form_name;
584 nt_forms_struct *tl;
587 * NT tries to add forms even when
588 * they are already in the base
589 * only update the values if already present
592 update=False;
594 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
595 for (n=0; n<*count; n++) {
596 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
597 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
598 update=True;
599 break;
603 if (update==False) {
604 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
605 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
606 return False;
608 *list = tl;
609 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
610 (*count)++;
613 (*list)[n].flag=form->flags;
614 (*list)[n].width=form->size_x;
615 (*list)[n].length=form->size_y;
616 (*list)[n].left=form->left;
617 (*list)[n].top=form->top;
618 (*list)[n].right=form->right;
619 (*list)[n].bottom=form->bottom;
621 return True;
624 /****************************************************************************
625 Delete a named form struct.
626 ****************************************************************************/
628 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
630 pstring key;
631 TDB_DATA kbuf;
632 int n=0;
633 fstring form_name;
635 *ret = WERR_OK;
637 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
639 for (n=0; n<*count; n++) {
640 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
641 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
642 break;
646 if (n == *count) {
647 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
648 *ret = WERR_INVALID_PARAM;
649 return False;
652 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
653 kbuf.dsize = strlen(key)+1;
654 kbuf.dptr = key;
655 if (tdb_delete(tdb_forms, kbuf) != 0) {
656 *ret = WERR_NOMEM;
657 return False;
660 return True;
663 /****************************************************************************
664 Update a form struct.
665 ****************************************************************************/
667 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
669 int n=0;
670 fstring form_name;
671 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
673 DEBUG(106, ("[%s]\n", form_name));
674 for (n=0; n<count; n++) {
675 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
676 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
677 break;
680 if (n==count) return;
682 (*list)[n].flag=form->flags;
683 (*list)[n].width=form->size_x;
684 (*list)[n].length=form->size_y;
685 (*list)[n].left=form->left;
686 (*list)[n].top=form->top;
687 (*list)[n].right=form->right;
688 (*list)[n].bottom=form->bottom;
691 /****************************************************************************
692 Get the nt drivers list.
693 Traverse the database and look-up the matching names.
694 ****************************************************************************/
695 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
697 int total=0;
698 const char *short_archi;
699 fstring *fl;
700 pstring key;
701 TDB_DATA kbuf, newkey;
703 short_archi = get_short_archi(architecture);
704 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
706 for (kbuf = tdb_firstkey(tdb_drivers);
707 kbuf.dptr;
708 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
710 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
711 continue;
713 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
714 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
715 return -1;
717 else *list = fl;
719 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
720 total++;
723 return(total);
726 /****************************************************************************
727 function to do the mapping between the long architecture name and
728 the short one.
729 ****************************************************************************/
730 const char *get_short_archi(const char *long_archi)
732 int i=-1;
734 DEBUG(107,("Getting architecture dependant directory\n"));
735 do {
736 i++;
737 } while ( (archi_table[i].long_archi!=NULL ) &&
738 StrCaseCmp(long_archi, archi_table[i].long_archi) );
740 if (archi_table[i].long_archi==NULL) {
741 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
742 return NULL;
745 /* this might be client code - but shouldn't this be an fstrcpy etc? */
748 DEBUGADD(108,("index: [%d]\n", i));
749 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
750 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
752 return archi_table[i].short_archi;
755 /****************************************************************************
756 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
757 There are two case to be covered here: PE (Portable Executable) and NE (New
758 Executable) files. Both files support the same INFO structure, but PE files
759 store the signature in unicode, and NE files store it as !unicode.
760 returns -1 on error, 1 on version info found, and 0 on no version info found.
761 ****************************************************************************/
763 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
765 int i;
766 char *buf = NULL;
767 ssize_t byte_count;
769 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
770 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
771 fname, PE_HEADER_SIZE));
772 goto error_exit;
775 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
776 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
777 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
778 fname, (unsigned long)byte_count));
779 goto no_version_info;
782 /* Is this really a DOS header? */
783 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
784 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
785 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
786 goto no_version_info;
789 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
790 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
791 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
792 fname, errno));
793 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
794 goto no_version_info;
797 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
798 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
799 fname, (unsigned long)byte_count));
800 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
801 goto no_version_info;
804 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
805 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
806 unsigned int num_sections;
807 unsigned int section_table_bytes;
809 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
810 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
811 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
812 /* At this point, we assume the file is in error. It still could be somthing
813 * else besides a PE file, but it unlikely at this point.
815 goto error_exit;
818 /* get the section table */
819 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
820 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
821 if (section_table_bytes == 0)
822 goto error_exit;
824 SAFE_FREE(buf);
825 if ((buf=malloc(section_table_bytes)) == NULL) {
826 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
827 fname, section_table_bytes));
828 goto error_exit;
831 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
832 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
833 fname, (unsigned long)byte_count));
834 goto error_exit;
837 /* Iterate the section table looking for the resource section ".rsrc" */
838 for (i = 0; i < num_sections; i++) {
839 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
841 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
842 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
843 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
845 if (section_bytes == 0)
846 goto error_exit;
848 SAFE_FREE(buf);
849 if ((buf=malloc(section_bytes)) == NULL) {
850 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
851 fname, section_bytes));
852 goto error_exit;
855 /* Seek to the start of the .rsrc section info */
856 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
857 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
858 fname, errno));
859 goto error_exit;
862 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
863 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
864 fname, (unsigned long)byte_count));
865 goto error_exit;
868 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
869 goto error_exit;
871 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
872 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
873 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
874 /* Align to next long address */
875 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
877 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
878 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
879 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
881 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
882 fname, *major, *minor,
883 (*major>>16)&0xffff, *major&0xffff,
884 (*minor>>16)&0xffff, *minor&0xffff));
885 SAFE_FREE(buf);
886 return 1;
893 /* Version info not found, fall back to origin date/time */
894 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
895 SAFE_FREE(buf);
896 return 0;
898 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
899 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
900 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
901 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
902 /* At this point, we assume the file is in error. It still could be somthing
903 * else besides a NE file, but it unlikely at this point. */
904 goto error_exit;
907 /* Allocate a bit more space to speed up things */
908 SAFE_FREE(buf);
909 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
910 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
911 fname, PE_HEADER_SIZE));
912 goto error_exit;
915 /* This is a HACK! I got tired of trying to sort through the messy
916 * 'NE' file format. If anyone wants to clean this up please have at
917 * it, but this works. 'NE' files will eventually fade away. JRR */
918 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
919 /* Cover case that should not occur in a well formed 'NE' .dll file */
920 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
922 for(i=0; i<byte_count; i++) {
923 /* Fast skip past data that can't possibly match */
924 if (buf[i] != 'V') continue;
926 /* Potential match data crosses buf boundry, move it to beginning
927 * of buf, and fill the buf with as much as it will hold. */
928 if (i>byte_count-VS_VERSION_INFO_SIZE) {
929 int bc;
931 memcpy(buf, &buf[i], byte_count-i);
932 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
933 (byte_count-i))) < 0) {
935 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
936 fname, errno));
937 goto error_exit;
940 byte_count = bc + (byte_count - i);
941 if (byte_count<VS_VERSION_INFO_SIZE) break;
943 i = 0;
946 /* Check that the full signature string and the magic number that
947 * follows exist (not a perfect solution, but the chances that this
948 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
949 * twice, as it is simpler to read the code. */
950 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
951 /* Compute skip alignment to next long address */
952 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
953 sizeof(VS_SIGNATURE)) & 3;
954 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
956 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
957 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
958 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
959 fname, *major, *minor,
960 (*major>>16)&0xffff, *major&0xffff,
961 (*minor>>16)&0xffff, *minor&0xffff));
962 SAFE_FREE(buf);
963 return 1;
968 /* Version info not found, fall back to origin date/time */
969 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
970 SAFE_FREE(buf);
971 return 0;
973 } else
974 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
975 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
976 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
978 no_version_info:
979 SAFE_FREE(buf);
980 return 0;
982 error_exit:
983 SAFE_FREE(buf);
984 return -1;
987 /****************************************************************************
988 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
989 share one or more files. During the MS installation process files are checked
990 to insure that only a newer version of a shared file is installed over an
991 older version. There are several possibilities for this comparison. If there
992 is no previous version, the new one is newer (obviously). If either file is
993 missing the version info structure, compare the creation date (on Unix use
994 the modification date). Otherwise chose the numerically larger version number.
995 ****************************************************************************/
997 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
999 BOOL use_version = True;
1000 pstring filepath;
1002 uint32 new_major;
1003 uint32 new_minor;
1004 time_t new_create_time;
1006 uint32 old_major;
1007 uint32 old_minor;
1008 time_t old_create_time;
1010 int access_mode;
1011 int action;
1012 files_struct *fsp = NULL;
1013 SMB_STRUCT_STAT st;
1014 SMB_STRUCT_STAT stat_buf;
1015 BOOL bad_path;
1017 ZERO_STRUCT(st);
1018 ZERO_STRUCT(stat_buf);
1019 new_create_time = (time_t)0;
1020 old_create_time = (time_t)0;
1022 /* Get file version info (if available) for previous file (if it exists) */
1023 pstrcpy(filepath, old_file);
1025 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1027 fsp = open_file_shared(conn, filepath, &stat_buf,
1028 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1029 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1030 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1031 if (!fsp) {
1032 /* Old file not found, so by definition new file is in fact newer */
1033 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1034 filepath, errno));
1035 return True;
1037 } else {
1038 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1039 if (ret == -1) goto error_exit;
1041 if (!ret) {
1042 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1043 old_file));
1044 use_version = False;
1045 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1046 old_create_time = st.st_mtime;
1047 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1050 close_file(fsp, True);
1052 /* Get file version info (if available) for new file */
1053 pstrcpy(filepath, new_file);
1054 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1056 fsp = open_file_shared(conn, filepath, &stat_buf,
1057 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1058 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1059 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1060 if (!fsp) {
1061 /* New file not found, this shouldn't occur if the caller did its job */
1062 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1063 filepath, errno));
1064 goto error_exit;
1066 } else {
1067 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1068 if (ret == -1) goto error_exit;
1070 if (!ret) {
1071 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1072 new_file));
1073 use_version = False;
1074 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1075 new_create_time = st.st_mtime;
1076 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1079 close_file(fsp, True);
1081 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1082 /* Compare versions and choose the larger version number */
1083 if (new_major > old_major ||
1084 (new_major == old_major && new_minor > old_minor)) {
1086 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1087 return True;
1089 else {
1090 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1091 return False;
1094 } else {
1095 /* Compare modification time/dates and choose the newest time/date */
1096 if (new_create_time > old_create_time) {
1097 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1098 return True;
1100 else {
1101 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1102 return False;
1106 error_exit:
1107 if(fsp)
1108 close_file(fsp, True);
1109 return -1;
1112 /****************************************************************************
1113 Determine the correct cVersion associated with an architecture and driver
1114 ****************************************************************************/
1115 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1116 struct current_user *user, WERROR *perr)
1118 int cversion;
1119 int access_mode;
1120 int action;
1121 NTSTATUS nt_status;
1122 pstring driverpath;
1123 DATA_BLOB null_pw;
1124 fstring res_type;
1125 files_struct *fsp = NULL;
1126 BOOL bad_path;
1127 SMB_STRUCT_STAT st;
1128 connection_struct *conn;
1130 ZERO_STRUCT(st);
1132 *perr = WERR_INVALID_PARAM;
1134 /* If architecture is Windows 95/98/ME, the version is always 0. */
1135 if (strcmp(architecture, "WIN40") == 0) {
1136 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1137 *perr = WERR_OK;
1138 return 0;
1142 * Connect to the print$ share under the same account as the user connected
1143 * to the rpc pipe. Note we must still be root to do this.
1146 /* Null password is ok - we are already an authenticated user... */
1147 null_pw = data_blob(NULL, 0);
1148 fstrcpy(res_type, "A:");
1149 become_root();
1150 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1151 unbecome_root();
1153 if (conn == NULL) {
1154 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1155 *perr = ntstatus_to_werror(nt_status);
1156 return -1;
1159 /* We are temporarily becoming the connection user. */
1160 if (!become_user(conn, user->vuid)) {
1161 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1162 *perr = WERR_ACCESS_DENIED;
1163 return -1;
1166 /* Open the driver file (Portable Executable format) and determine the
1167 * deriver the cversion. */
1168 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1170 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1172 fsp = open_file_shared(conn, driverpath, &st,
1173 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1174 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1175 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1176 if (!fsp) {
1177 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1178 driverpath, errno));
1179 *perr = WERR_ACCESS_DENIED;
1180 goto error_exit;
1182 else {
1183 uint32 major;
1184 uint32 minor;
1185 int ret = get_file_version(fsp, driverpath, &major, &minor);
1186 if (ret == -1) goto error_exit;
1188 if (!ret) {
1189 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1190 goto error_exit;
1194 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1195 * for more details. Version in this case is not just the version of the
1196 * file, but the version in the sense of kernal mode (2) vs. user mode
1197 * (3) drivers. Other bits of the version fields are the version info.
1198 * JRR 010716
1200 cversion = major & 0x0000ffff;
1201 switch (cversion) {
1202 case 2: /* WinNT drivers */
1203 case 3: /* Win2K drivers */
1204 break;
1206 default:
1207 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1208 driverpath, cversion));
1209 goto error_exit;
1212 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1213 driverpath, major, minor));
1216 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1217 driverpath, cversion));
1219 close_file(fsp, True);
1220 close_cnum(conn, user->vuid);
1221 unbecome_user();
1222 *perr = WERR_OK;
1223 return cversion;
1226 error_exit:
1228 if(fsp)
1229 close_file(fsp, True);
1231 close_cnum(conn, user->vuid);
1232 unbecome_user();
1233 return -1;
1236 /****************************************************************************
1237 ****************************************************************************/
1238 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1239 struct current_user *user)
1241 const char *architecture;
1242 fstring new_name;
1243 char *p;
1244 int i;
1245 WERROR err;
1247 /* clean up the driver name.
1248 * we can get .\driver.dll
1249 * or worse c:\windows\system\driver.dll !
1251 /* using an intermediate string to not have overlaping memcpy()'s */
1252 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1253 fstrcpy(new_name, p+1);
1254 fstrcpy(driver->driverpath, new_name);
1257 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1258 fstrcpy(new_name, p+1);
1259 fstrcpy(driver->datafile, new_name);
1262 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1263 fstrcpy(new_name, p+1);
1264 fstrcpy(driver->configfile, new_name);
1267 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1268 fstrcpy(new_name, p+1);
1269 fstrcpy(driver->helpfile, new_name);
1272 if (driver->dependentfiles) {
1273 for (i=0; *driver->dependentfiles[i]; i++) {
1274 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1275 fstrcpy(new_name, p+1);
1276 fstrcpy(driver->dependentfiles[i], new_name);
1281 architecture = get_short_archi(driver->environment);
1283 /* jfm:7/16/2000 the client always sends the cversion=0.
1284 * The server should check which version the driver is by reading
1285 * the PE header of driver->driverpath.
1287 * For Windows 95/98 the version is 0 (so the value sent is correct)
1288 * For Windows NT (the architecture doesn't matter)
1289 * NT 3.1: cversion=0
1290 * NT 3.5/3.51: cversion=1
1291 * NT 4: cversion=2
1292 * NT2K: cversion=3
1294 if ((driver->cversion = get_correct_cversion( architecture,
1295 driver->driverpath, user, &err)) == -1)
1296 return err;
1298 return WERR_OK;
1301 /****************************************************************************
1302 ****************************************************************************/
1303 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1305 const char *architecture;
1306 fstring new_name;
1307 char *p;
1308 int i;
1309 WERROR err;
1311 /* clean up the driver name.
1312 * we can get .\driver.dll
1313 * or worse c:\windows\system\driver.dll !
1315 /* using an intermediate string to not have overlaping memcpy()'s */
1316 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1317 fstrcpy(new_name, p+1);
1318 fstrcpy(driver->driverpath, new_name);
1321 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1322 fstrcpy(new_name, p+1);
1323 fstrcpy(driver->datafile, new_name);
1326 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1327 fstrcpy(new_name, p+1);
1328 fstrcpy(driver->configfile, new_name);
1331 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1332 fstrcpy(new_name, p+1);
1333 fstrcpy(driver->helpfile, new_name);
1336 if (driver->dependentfiles) {
1337 for (i=0; *driver->dependentfiles[i]; i++) {
1338 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1339 fstrcpy(new_name, p+1);
1340 fstrcpy(driver->dependentfiles[i], new_name);
1345 architecture = get_short_archi(driver->environment);
1347 /* jfm:7/16/2000 the client always sends the cversion=0.
1348 * The server should check which version the driver is by reading
1349 * the PE header of driver->driverpath.
1351 * For Windows 95/98 the version is 0 (so the value sent is correct)
1352 * For Windows NT (the architecture doesn't matter)
1353 * NT 3.1: cversion=0
1354 * NT 3.5/3.51: cversion=1
1355 * NT 4: cversion=2
1356 * NT2K: cversion=3
1358 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1359 return err;
1361 return WERR_OK;
1364 /****************************************************************************
1365 ****************************************************************************/
1366 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1367 uint32 level, struct current_user *user)
1369 switch (level) {
1370 case 3:
1372 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1373 driver=driver_abstract.info_3;
1374 return clean_up_driver_struct_level_3(driver, user);
1376 case 6:
1378 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1379 driver=driver_abstract.info_6;
1380 return clean_up_driver_struct_level_6(driver, user);
1382 default:
1383 return WERR_INVALID_PARAM;
1387 /****************************************************************************
1388 This function sucks and should be replaced. JRA.
1389 ****************************************************************************/
1391 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1393 dst->cversion = src->version;
1395 fstrcpy( dst->name, src->name);
1396 fstrcpy( dst->environment, src->environment);
1397 fstrcpy( dst->driverpath, src->driverpath);
1398 fstrcpy( dst->datafile, src->datafile);
1399 fstrcpy( dst->configfile, src->configfile);
1400 fstrcpy( dst->helpfile, src->helpfile);
1401 fstrcpy( dst->monitorname, src->monitorname);
1402 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1403 dst->dependentfiles = src->dependentfiles;
1406 #if 0 /* Debugging function */
1408 static char* ffmt(unsigned char *c){
1409 int i;
1410 static char ffmt_str[17];
1412 for (i=0; i<16; i++) {
1413 if ((c[i] < ' ') || (c[i] > '~'))
1414 ffmt_str[i]='.';
1415 else
1416 ffmt_str[i]=c[i];
1418 ffmt_str[16]='\0';
1419 return ffmt_str;
1422 #endif
1424 /****************************************************************************
1425 ****************************************************************************/
1426 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1427 struct current_user *user, WERROR *perr)
1429 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1430 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1431 const char *architecture;
1432 pstring new_dir;
1433 pstring old_name;
1434 pstring new_name;
1435 DATA_BLOB null_pw;
1436 connection_struct *conn;
1437 NTSTATUS nt_status;
1438 pstring inbuf;
1439 pstring outbuf;
1440 fstring res_type;
1441 BOOL bad_path;
1442 SMB_STRUCT_STAT st;
1443 int ver = 0;
1444 int i;
1446 memset(inbuf, '\0', sizeof(inbuf));
1447 memset(outbuf, '\0', sizeof(outbuf));
1448 *perr = WERR_OK;
1450 if (level==3)
1451 driver=driver_abstract.info_3;
1452 else if (level==6) {
1453 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1454 driver = &converted_driver;
1455 } else {
1456 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1457 return False;
1460 architecture = get_short_archi(driver->environment);
1463 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1464 * Note we must be root to do this.
1467 null_pw = data_blob(NULL, 0);
1468 fstrcpy(res_type, "A:");
1469 become_root();
1470 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1471 unbecome_root();
1473 if (conn == NULL) {
1474 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1475 *perr = ntstatus_to_werror(nt_status);
1476 return False;
1480 * Save who we are - we are temporarily becoming the connection user.
1483 if (!become_user(conn, conn->vuid)) {
1484 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1485 return False;
1489 * make the directories version and version\driver_name
1490 * under the architecture directory.
1492 DEBUG(5,("Creating first directory\n"));
1493 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1494 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1495 mkdir_internal(conn, new_dir);
1497 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1498 * listed for this driver which has already been moved, skip it (note:
1499 * drivers may list the same file name several times. Then check if the
1500 * file already exists in archi\cversion\, if so, check that the version
1501 * info (or time stamps if version info is unavailable) is newer (or the
1502 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1503 * Otherwise, delete the file.
1505 * If a file is not moved to archi\cversion\ because of an error, all the
1506 * rest of the 'unmoved' driver files are removed from archi\. If one or
1507 * more of the driver's files was already moved to archi\cversion\, it
1508 * potentially leaves the driver in a partially updated state. Version
1509 * trauma will most likely occur if an client attempts to use any printer
1510 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1511 * done is appropriate... later JRR
1514 DEBUG(5,("Moving files now !\n"));
1516 if (driver->driverpath && strlen(driver->driverpath)) {
1517 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1518 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1519 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1520 NTSTATUS status;
1521 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1522 status = rename_internals(conn, new_name, old_name, 0, True);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1525 new_name, old_name));
1526 *perr = ntstatus_to_werror(status);
1527 unlink_internals(conn, 0, new_name);
1528 ver = -1;
1530 } else {
1531 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1532 unlink_internals(conn, 0, new_name);
1536 if (driver->datafile && strlen(driver->datafile)) {
1537 if (!strequal(driver->datafile, driver->driverpath)) {
1538 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1539 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1540 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1541 NTSTATUS status;
1542 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1543 status = rename_internals(conn, new_name, old_name, 0, True);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1546 new_name, old_name));
1547 *perr = ntstatus_to_werror(status);
1548 unlink_internals(conn, 0, new_name);
1549 ver = -1;
1551 } else {
1552 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1553 unlink_internals(conn, 0, new_name);
1558 if (driver->configfile && strlen(driver->configfile)) {
1559 if (!strequal(driver->configfile, driver->driverpath) &&
1560 !strequal(driver->configfile, driver->datafile)) {
1561 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1562 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1563 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1564 NTSTATUS status;
1565 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1566 status = rename_internals(conn, new_name, old_name, 0, True);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1569 new_name, old_name));
1570 *perr = ntstatus_to_werror(status);
1571 unlink_internals(conn, 0, new_name);
1572 ver = -1;
1574 } else {
1575 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1576 unlink_internals(conn, 0, new_name);
1581 if (driver->helpfile && strlen(driver->helpfile)) {
1582 if (!strequal(driver->helpfile, driver->driverpath) &&
1583 !strequal(driver->helpfile, driver->datafile) &&
1584 !strequal(driver->helpfile, driver->configfile)) {
1585 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1586 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1587 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1588 NTSTATUS status;
1589 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1590 status = rename_internals(conn, new_name, old_name, 0, True);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1593 new_name, old_name));
1594 *perr = ntstatus_to_werror(status);
1595 unlink_internals(conn, 0, new_name);
1596 ver = -1;
1598 } else {
1599 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1600 unlink_internals(conn, 0, new_name);
1605 if (driver->dependentfiles) {
1606 for (i=0; *driver->dependentfiles[i]; i++) {
1607 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1608 !strequal(driver->dependentfiles[i], driver->datafile) &&
1609 !strequal(driver->dependentfiles[i], driver->configfile) &&
1610 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1611 int j;
1612 for (j=0; j < i; j++) {
1613 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1614 goto NextDriver;
1618 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1619 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1620 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1621 NTSTATUS status;
1622 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1623 status = rename_internals(conn, new_name, old_name, 0, True);
1624 if (!NT_STATUS_IS_OK(status)) {
1625 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1626 new_name, old_name));
1627 *perr = ntstatus_to_werror(status);
1628 unlink_internals(conn, 0, new_name);
1629 ver = -1;
1631 } else {
1632 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1633 unlink_internals(conn, 0, new_name);
1636 NextDriver: ;
1640 close_cnum(conn, user->vuid);
1641 unbecome_user();
1643 return ver == -1 ? False : True;
1646 /****************************************************************************
1647 ****************************************************************************/
1648 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1650 int len, buflen;
1651 const char *architecture;
1652 pstring directory;
1653 fstring temp_name;
1654 pstring key;
1655 char *buf;
1656 int i, ret;
1657 TDB_DATA kbuf, dbuf;
1659 architecture = get_short_archi(driver->environment);
1661 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1662 * \\server is added in the rpc server layer.
1663 * It does make sense to NOT store the server's name in the printer TDB.
1666 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1668 /* .inf files do not always list a file for each of the four standard files.
1669 * Don't prepend a path to a null filename, or client claims:
1670 * "The server on which the printer resides does not have a suitable
1671 * <printer driver name> printer driver installed. Click OK if you
1672 * wish to install the driver on your local machine."
1674 if (strlen(driver->driverpath)) {
1675 fstrcpy(temp_name, driver->driverpath);
1676 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1679 if (strlen(driver->datafile)) {
1680 fstrcpy(temp_name, driver->datafile);
1681 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1684 if (strlen(driver->configfile)) {
1685 fstrcpy(temp_name, driver->configfile);
1686 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1689 if (strlen(driver->helpfile)) {
1690 fstrcpy(temp_name, driver->helpfile);
1691 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1694 if (driver->dependentfiles) {
1695 for (i=0; *driver->dependentfiles[i]; i++) {
1696 fstrcpy(temp_name, driver->dependentfiles[i]);
1697 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1701 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1703 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1705 buf = NULL;
1706 len = buflen = 0;
1708 again:
1709 len = 0;
1710 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1711 driver->cversion,
1712 driver->name,
1713 driver->environment,
1714 driver->driverpath,
1715 driver->datafile,
1716 driver->configfile,
1717 driver->helpfile,
1718 driver->monitorname,
1719 driver->defaultdatatype);
1721 if (driver->dependentfiles) {
1722 for (i=0; *driver->dependentfiles[i]; i++) {
1723 len += tdb_pack(buf+len, buflen-len, "f",
1724 driver->dependentfiles[i]);
1728 if (len != buflen) {
1729 char *tb;
1731 tb = (char *)Realloc(buf, len);
1732 if (!tb) {
1733 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1734 ret = -1;
1735 goto done;
1737 else buf = tb;
1738 buflen = len;
1739 goto again;
1743 kbuf.dptr = key;
1744 kbuf.dsize = strlen(key)+1;
1745 dbuf.dptr = buf;
1746 dbuf.dsize = len;
1748 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1750 done:
1751 if (ret)
1752 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1754 SAFE_FREE(buf);
1755 return ret;
1758 /****************************************************************************
1759 ****************************************************************************/
1760 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1762 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1764 ZERO_STRUCT(info3);
1765 info3.cversion = driver->version;
1766 fstrcpy(info3.name,driver->name);
1767 fstrcpy(info3.environment,driver->environment);
1768 fstrcpy(info3.driverpath,driver->driverpath);
1769 fstrcpy(info3.datafile,driver->datafile);
1770 fstrcpy(info3.configfile,driver->configfile);
1771 fstrcpy(info3.helpfile,driver->helpfile);
1772 fstrcpy(info3.monitorname,driver->monitorname);
1773 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1774 info3.dependentfiles = driver->dependentfiles;
1776 return add_a_printer_driver_3(&info3);
1780 /****************************************************************************
1781 ****************************************************************************/
1782 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1784 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1786 ZERO_STRUCT(info);
1788 fstrcpy(info.name, driver);
1789 fstrcpy(info.defaultdatatype, "RAW");
1791 fstrcpy(info.driverpath, "");
1792 fstrcpy(info.datafile, "");
1793 fstrcpy(info.configfile, "");
1794 fstrcpy(info.helpfile, "");
1796 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1797 return WERR_NOMEM;
1799 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1800 fstrcpy(info.dependentfiles[0], "");
1802 *info_ptr = memdup(&info, sizeof(info));
1804 return WERR_OK;
1807 /****************************************************************************
1808 ****************************************************************************/
1809 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1811 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1812 TDB_DATA kbuf, dbuf;
1813 const char *architecture;
1814 int len = 0;
1815 int i;
1816 pstring key;
1818 ZERO_STRUCT(driver);
1820 architecture = get_short_archi(arch);
1822 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1824 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1825 version = 0;
1827 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1829 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1831 kbuf.dptr = key;
1832 kbuf.dsize = strlen(key)+1;
1834 dbuf = tdb_fetch(tdb_drivers, kbuf);
1835 if (!dbuf.dptr)
1836 return WERR_UNKNOWN_PRINTER_DRIVER;
1838 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1839 &driver.cversion,
1840 driver.name,
1841 driver.environment,
1842 driver.driverpath,
1843 driver.datafile,
1844 driver.configfile,
1845 driver.helpfile,
1846 driver.monitorname,
1847 driver.defaultdatatype);
1849 i=0;
1850 while (len < dbuf.dsize) {
1851 fstring *tddfs;
1853 tddfs = (fstring *)Realloc(driver.dependentfiles,
1854 sizeof(fstring)*(i+2));
1855 if (tddfs == NULL) {
1856 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1857 break;
1859 else driver.dependentfiles = tddfs;
1861 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1862 &driver.dependentfiles[i]);
1863 i++;
1866 if (driver.dependentfiles != NULL)
1867 fstrcpy(driver.dependentfiles[i], "");
1869 SAFE_FREE(dbuf.dptr);
1871 if (len != dbuf.dsize) {
1872 SAFE_FREE(driver.dependentfiles);
1874 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1877 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1879 return WERR_OK;
1882 /****************************************************************************
1883 Debugging function, dump at level 6 the struct in the logs.
1884 ****************************************************************************/
1886 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1888 uint32 result;
1889 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1890 int i;
1892 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1894 switch (level)
1896 case 3:
1898 if (driver.info_3 == NULL)
1899 result=5;
1900 else {
1901 info3=driver.info_3;
1903 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1904 DEBUGADD(20,("name:[%s]\n", info3->name));
1905 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1906 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1907 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1908 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1909 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1910 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1911 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1913 for (i=0; info3->dependentfiles &&
1914 *info3->dependentfiles[i]; i++) {
1915 DEBUGADD(20,("dependentfile:[%s]\n",
1916 info3->dependentfiles[i]));
1918 result=0;
1920 break;
1922 default:
1923 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1924 result=1;
1925 break;
1928 return result;
1931 /****************************************************************************
1932 ****************************************************************************/
1933 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1935 int len = 0;
1937 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1939 if (!nt_devmode)
1940 return len;
1942 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1943 nt_devmode->devicename,
1944 nt_devmode->formname,
1946 nt_devmode->specversion,
1947 nt_devmode->driverversion,
1948 nt_devmode->size,
1949 nt_devmode->driverextra,
1950 nt_devmode->orientation,
1951 nt_devmode->papersize,
1952 nt_devmode->paperlength,
1953 nt_devmode->paperwidth,
1954 nt_devmode->scale,
1955 nt_devmode->copies,
1956 nt_devmode->defaultsource,
1957 nt_devmode->printquality,
1958 nt_devmode->color,
1959 nt_devmode->duplex,
1960 nt_devmode->yresolution,
1961 nt_devmode->ttoption,
1962 nt_devmode->collate,
1963 nt_devmode->logpixels,
1965 nt_devmode->fields,
1966 nt_devmode->bitsperpel,
1967 nt_devmode->pelswidth,
1968 nt_devmode->pelsheight,
1969 nt_devmode->displayflags,
1970 nt_devmode->displayfrequency,
1971 nt_devmode->icmmethod,
1972 nt_devmode->icmintent,
1973 nt_devmode->mediatype,
1974 nt_devmode->dithertype,
1975 nt_devmode->reserved1,
1976 nt_devmode->reserved2,
1977 nt_devmode->panningwidth,
1978 nt_devmode->panningheight,
1979 nt_devmode->private);
1982 if (nt_devmode->private) {
1983 len += tdb_pack(buf+len, buflen-len, "B",
1984 nt_devmode->driverextra,
1985 nt_devmode->private);
1988 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1990 return len;
1993 /****************************************************************************
1994 Pack all values in all printer keys
1995 ***************************************************************************/
1997 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1999 int len = 0;
2000 int i, j;
2001 REGISTRY_VALUE *val;
2002 REGVAL_CTR *val_ctr;
2003 pstring path;
2004 int num_values;
2006 if ( !data )
2007 return 0;
2009 /* loop over all keys */
2011 for ( i=0; i<data->num_keys; i++ ) {
2012 val_ctr = &data->keys[i].values;
2013 num_values = regval_ctr_numvals( val_ctr );
2015 /* loop over all values */
2017 for ( j=0; j<num_values; j++ ) {
2018 /* pathname should be stored as <key>\<value> */
2020 val = regval_ctr_specific_value( val_ctr, j );
2021 pstrcpy( path, data->keys[i].name );
2022 pstrcat( path, "\\" );
2023 pstrcat( path, regval_name(val) );
2025 len += tdb_pack(buf+len, buflen-len, "pPdB",
2026 val,
2027 path,
2028 regval_type(val),
2029 regval_size(val),
2030 regval_data_p(val) );
2035 /* terminator */
2037 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2039 return len;
2043 /****************************************************************************
2044 Delete a printer - this just deletes the printer info file, any open
2045 handles are not affected.
2046 ****************************************************************************/
2048 uint32 del_a_printer(char *sharename)
2050 pstring key;
2051 TDB_DATA kbuf;
2053 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2055 kbuf.dptr=key;
2056 kbuf.dsize=strlen(key)+1;
2058 tdb_delete(tdb_printers, kbuf);
2059 return 0;
2062 /****************************************************************************
2063 ****************************************************************************/
2064 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2066 pstring key;
2067 char *buf;
2068 int buflen, len;
2069 WERROR ret;
2070 TDB_DATA kbuf, dbuf;
2073 * in addprinter: no servername and the printer is the name
2074 * in setprinter: servername is \\server
2075 * and printer is \\server\\printer
2077 * Samba manages only local printers.
2078 * we currently don't support things like i
2079 * path=\\other_server\printer
2081 * We only store the printername, not \\server\printername
2084 if ( info->servername[0] != '\0' ) {
2085 trim_string(info->printername, info->servername, NULL);
2086 trim_char(info->printername, '\\', '\0');
2087 info->servername[0]='\0';
2091 * JFM: one day I'll forget.
2092 * below that's info->portname because that's the SAMBA sharename
2093 * and I made NT 'thinks' it's the portname
2094 * the info->sharename is the thing you can name when you add a printer
2095 * that's the short-name when you create shared printer for 95/98
2096 * So I've made a limitation in SAMBA: you can only have 1 printer model
2097 * behind a SAMBA share.
2100 buf = NULL;
2101 buflen = 0;
2103 again:
2104 len = 0;
2105 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2106 info->attributes,
2107 info->priority,
2108 info->default_priority,
2109 info->starttime,
2110 info->untiltime,
2111 info->status,
2112 info->cjobs,
2113 info->averageppm,
2114 info->changeid,
2115 info->c_setprinter,
2116 info->setuptime,
2117 info->servername,
2118 info->printername,
2119 info->sharename,
2120 info->portname,
2121 info->drivername,
2122 info->comment,
2123 info->location,
2124 info->sepfile,
2125 info->printprocessor,
2126 info->datatype,
2127 info->parameters);
2129 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2131 len += pack_values( &info->data, buf+len, buflen-len );
2133 if (buflen != len) {
2134 char *tb;
2136 tb = (char *)Realloc(buf, len);
2137 if (!tb) {
2138 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2139 ret = WERR_NOMEM;
2140 goto done;
2142 else buf = tb;
2143 buflen = len;
2144 goto again;
2148 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2150 kbuf.dptr = key;
2151 kbuf.dsize = strlen(key)+1;
2152 dbuf.dptr = buf;
2153 dbuf.dsize = len;
2155 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2157 done:
2158 if (!W_ERROR_IS_OK(ret))
2159 DEBUG(8, ("error updating printer to tdb on disk\n"));
2161 SAFE_FREE(buf);
2163 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2164 info->sharename, info->drivername, info->portname, len));
2166 return ret;
2170 /****************************************************************************
2171 Malloc and return an NT devicemode.
2172 ****************************************************************************/
2174 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2177 char adevice[MAXDEVICENAME];
2178 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2180 if (nt_devmode == NULL) {
2181 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2182 return NULL;
2185 ZERO_STRUCTP(nt_devmode);
2187 slprintf(adevice, sizeof(adevice), "%s", default_devicename);
2188 fstrcpy(nt_devmode->devicename, adevice);
2190 fstrcpy(nt_devmode->formname, "Letter");
2192 nt_devmode->specversion = 0x0401;
2193 nt_devmode->driverversion = 0x0400;
2194 nt_devmode->size = 0x00DC;
2195 nt_devmode->driverextra = 0x0000;
2196 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2197 DEFAULTSOURCE | COPIES | SCALE |
2198 PAPERSIZE | ORIENTATION;
2199 nt_devmode->orientation = 1;
2200 nt_devmode->papersize = PAPER_LETTER;
2201 nt_devmode->paperlength = 0;
2202 nt_devmode->paperwidth = 0;
2203 nt_devmode->scale = 0x64;
2204 nt_devmode->copies = 1;
2205 nt_devmode->defaultsource = BIN_FORMSOURCE;
2206 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2207 nt_devmode->color = COLOR_MONOCHROME;
2208 nt_devmode->duplex = DUP_SIMPLEX;
2209 nt_devmode->yresolution = 0;
2210 nt_devmode->ttoption = TT_SUBDEV;
2211 nt_devmode->collate = COLLATE_FALSE;
2212 nt_devmode->icmmethod = 0;
2213 nt_devmode->icmintent = 0;
2214 nt_devmode->mediatype = 0;
2215 nt_devmode->dithertype = 0;
2217 /* non utilisés par un driver d'imprimante */
2218 nt_devmode->logpixels = 0;
2219 nt_devmode->bitsperpel = 0;
2220 nt_devmode->pelswidth = 0;
2221 nt_devmode->pelsheight = 0;
2222 nt_devmode->displayflags = 0;
2223 nt_devmode->displayfrequency = 0;
2224 nt_devmode->reserved1 = 0;
2225 nt_devmode->reserved2 = 0;
2226 nt_devmode->panningwidth = 0;
2227 nt_devmode->panningheight = 0;
2229 nt_devmode->private = NULL;
2230 return nt_devmode;
2233 /****************************************************************************
2234 Deepcopy an NT devicemode.
2235 ****************************************************************************/
2237 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2239 NT_DEVICEMODE *new_nt_devicemode = NULL;
2241 if ( !nt_devicemode )
2242 return NULL;
2244 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2245 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2246 return NULL;
2249 new_nt_devicemode->private = NULL;
2250 if (nt_devicemode->private != NULL) {
2251 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2252 SAFE_FREE(new_nt_devicemode);
2253 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2254 return NULL;
2258 return new_nt_devicemode;
2261 /****************************************************************************
2262 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2263 ****************************************************************************/
2265 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2267 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2269 if(nt_devmode == NULL)
2270 return;
2272 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2274 SAFE_FREE(nt_devmode->private);
2275 SAFE_FREE(*devmode_ptr);
2278 /****************************************************************************
2279 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2280 ****************************************************************************/
2281 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2283 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2284 NT_PRINTER_DATA *data;
2285 int i;
2287 if ( !info )
2288 return;
2290 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2292 free_nt_devicemode(&info->devmode);
2294 /* clean up all registry keys */
2296 data = &info->data;
2297 for ( i=0; i<data->num_keys; i++ ) {
2298 SAFE_FREE( data->keys[i].name );
2299 regval_ctr_destroy( &data->keys[i].values );
2301 SAFE_FREE( data->keys );
2303 /* finally the top level structure */
2305 SAFE_FREE( *info_ptr );
2309 /****************************************************************************
2310 ****************************************************************************/
2311 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2313 int len = 0;
2314 int extra_len = 0;
2315 NT_DEVICEMODE devmode;
2317 ZERO_STRUCT(devmode);
2319 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2321 if (!*nt_devmode) return len;
2323 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2324 devmode.devicename,
2325 devmode.formname,
2327 &devmode.specversion,
2328 &devmode.driverversion,
2329 &devmode.size,
2330 &devmode.driverextra,
2331 &devmode.orientation,
2332 &devmode.papersize,
2333 &devmode.paperlength,
2334 &devmode.paperwidth,
2335 &devmode.scale,
2336 &devmode.copies,
2337 &devmode.defaultsource,
2338 &devmode.printquality,
2339 &devmode.color,
2340 &devmode.duplex,
2341 &devmode.yresolution,
2342 &devmode.ttoption,
2343 &devmode.collate,
2344 &devmode.logpixels,
2346 &devmode.fields,
2347 &devmode.bitsperpel,
2348 &devmode.pelswidth,
2349 &devmode.pelsheight,
2350 &devmode.displayflags,
2351 &devmode.displayfrequency,
2352 &devmode.icmmethod,
2353 &devmode.icmintent,
2354 &devmode.mediatype,
2355 &devmode.dithertype,
2356 &devmode.reserved1,
2357 &devmode.reserved2,
2358 &devmode.panningwidth,
2359 &devmode.panningheight,
2360 &devmode.private);
2362 if (devmode.private) {
2363 /* the len in tdb_unpack is an int value and
2364 * devmode.driverextra is only a short
2366 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2367 devmode.driverextra=(uint16)extra_len;
2369 /* check to catch an invalid TDB entry so we don't segfault */
2370 if (devmode.driverextra == 0) {
2371 devmode.private = NULL;
2375 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2377 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2378 if (devmode.private)
2379 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2381 return len;
2384 /****************************************************************************
2385 Allocate and initialize a new slot.
2386 ***************************************************************************/
2388 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2390 NT_PRINTER_KEY *d;
2391 int key_index;
2393 if ( !data || !name )
2394 return -1;
2396 /* allocate another slot in the NT_PRINTER_KEY array */
2398 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2399 if ( d )
2400 data->keys = d;
2402 key_index = data->num_keys;
2404 /* initialze new key */
2406 data->num_keys++;
2407 data->keys[key_index].name = strdup( name );
2409 ZERO_STRUCTP( &data->keys[key_index].values );
2411 regval_ctr_init( &data->keys[key_index].values );
2413 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2415 return key_index;
2418 /****************************************************************************
2419 search for a registry key name in the existing printer data
2420 ***************************************************************************/
2422 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2424 int key_index = -1;
2425 int i;
2427 if ( !data || !name )
2428 return -1;
2430 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2432 /* loop over all existing keys */
2434 for ( i=0; i<data->num_keys; i++ ) {
2435 if ( strequal(data->keys[i].name, name) ) {
2436 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2437 key_index = i;
2438 break;
2443 return key_index;
2446 /****************************************************************************
2447 ***************************************************************************/
2449 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2451 int i, j;
2452 int key_len;
2453 int num_subkeys = 0;
2454 char *p;
2455 fstring *ptr, *subkeys_ptr = NULL;
2456 fstring subkeyname;
2458 if ( !data )
2459 return 0;
2461 for ( i=0; i<data->num_keys; i++ ) {
2462 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2463 /* match sure it is a subkey and not the key itself */
2465 key_len = strlen( key );
2466 if ( strlen(data->keys[i].name) == key_len )
2467 continue;
2469 /* get subkey path */
2471 p = data->keys[i].name + key_len;
2472 if ( *p == '\\' )
2473 p++;
2474 fstrcpy( subkeyname, p );
2475 if ( (p = strchr( subkeyname, '\\' )) )
2476 *p = '\0';
2478 /* don't add a key more than once */
2480 for ( j=0; j<num_subkeys; j++ ) {
2481 if ( strequal( subkeys_ptr[j], subkeyname ) )
2482 break;
2485 if ( j != num_subkeys )
2486 continue;
2488 /* found a match, so allocate space and copy the name */
2490 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2491 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2492 num_subkeys+1));
2493 SAFE_FREE( subkeys );
2494 return 0;
2497 subkeys_ptr = ptr;
2498 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2499 num_subkeys++;
2504 /* tag of the end */
2506 if (num_subkeys)
2507 fstrcpy(subkeys_ptr[num_subkeys], "" );
2509 *subkeys = subkeys_ptr;
2511 return num_subkeys;
2514 #ifdef HAVE_ADS
2515 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2516 const char *sz)
2518 smb_ucs2_t conv_str[1024];
2519 size_t str_size;
2521 regval_ctr_delvalue(ctr, val_name);
2522 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2523 STR_TERMINATE | STR_NOALIGN);
2524 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2525 (char *) conv_str, str_size);
2528 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2529 uint32 dword)
2531 regval_ctr_delvalue(ctr, val_name);
2532 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2533 (char *) &dword, sizeof(dword));
2536 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2537 BOOL b)
2539 uint8 bin_bool = (b ? 1 : 0);
2540 regval_ctr_delvalue(ctr, val_name);
2541 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2542 (char *) &bin_bool, sizeof(bin_bool));
2545 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2546 const char *multi_sz)
2548 smb_ucs2_t *conv_strs = NULL;
2549 size_t str_size;
2551 /* a multi-sz has to have a null string terminator, i.e., the last
2552 string must be followed by two nulls */
2553 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2554 conv_strs = calloc(str_size, 1);
2556 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2557 STR_TERMINATE | STR_NOALIGN);
2559 regval_ctr_delvalue(ctr, val_name);
2560 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2561 (char *) conv_strs, str_size);
2562 safe_free(conv_strs);
2566 /****************************************************************************
2567 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2569 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2570 * @return BOOL indicating success or failure
2571 ***************************************************************************/
2573 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2575 REGVAL_CTR *ctr = NULL;
2576 fstring longname;
2577 char *allocated_string = NULL;
2578 const char *ascii_str;
2579 int i;
2581 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2582 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2583 ctr = &info2->data.keys[i].values;
2585 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2586 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2588 get_mydnsfullname(longname);
2589 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2591 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2592 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2593 SAFE_FREE(allocated_string);
2595 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2596 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2597 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2598 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2599 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2600 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2601 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2602 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2603 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2605 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2606 (info2->attributes &
2607 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2609 switch (info2->attributes & 0x3) {
2610 case 0:
2611 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2612 break;
2613 case 1:
2614 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2615 break;
2616 case 2:
2617 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2618 break;
2619 default:
2620 ascii_str = "unknown";
2622 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2624 return True;
2627 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2628 struct uuid guid)
2630 int i;
2631 REGVAL_CTR *ctr=NULL;
2633 /* find the DsSpooler key */
2634 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2635 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2636 ctr = &info2->data.keys[i].values;
2638 regval_ctr_delvalue(ctr, "objectGUID");
2639 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2640 (char *) &guid, sizeof(struct uuid));
2643 static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
2644 NT_PRINTER_INFO_LEVEL *printer)
2646 ADS_STATUS ads_rc;
2647 void *res;
2648 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2649 char *srv_dn_utf8, **srv_cn_utf8;
2650 TALLOC_CTX *ctx;
2651 ADS_MODLIST mods;
2652 const char *attrs[] = {"objectGUID", NULL};
2653 struct uuid guid;
2654 WERROR win_rc = WERR_OK;
2656 DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
2658 /* figure out where to publish */
2659 ads_find_machine_acct(ads, &res, global_myname());
2661 /* We use ldap_get_dn here as we need the answer
2662 * in utf8 to call ldap_explode_dn(). JRA. */
2664 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2665 if (!srv_dn_utf8) {
2666 ads_destroy(&ads);
2667 return WERR_SERVER_UNAVAILABLE;
2669 ads_msgfree(ads, res);
2670 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2671 if (!srv_cn_utf8) {
2672 ldap_memfree(srv_dn_utf8);
2673 ads_destroy(&ads);
2674 return WERR_SERVER_UNAVAILABLE;
2676 /* Now convert to CH_UNIX. */
2677 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2678 ldap_memfree(srv_dn_utf8);
2679 ldap_memfree(srv_cn_utf8);
2680 ads_destroy(&ads);
2681 return WERR_SERVER_UNAVAILABLE;
2683 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2684 ldap_memfree(srv_dn_utf8);
2685 ldap_memfree(srv_cn_utf8);
2686 ads_destroy(&ads);
2687 SAFE_FREE(srv_dn);
2688 return WERR_SERVER_UNAVAILABLE;
2691 ldap_memfree(srv_dn_utf8);
2692 ldap_memfree(srv_cn_utf8);
2694 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2695 printer->info_2->sharename, srv_dn);
2697 SAFE_FREE(srv_dn);
2698 SAFE_FREE(srv_cn_0);
2700 /* build the ads mods */
2701 ctx = talloc_init("nt_printer_publish_ads");
2702 mods = ads_init_mods(ctx);
2704 get_local_printer_publishing_data(ctx, &mods,
2705 &printer->info_2->data);
2706 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2707 printer->info_2->sharename);
2709 /* publish it */
2710 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
2711 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT)
2712 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2714 if (!ADS_ERR_OK(ads_rc))
2715 DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
2717 talloc_destroy(ctx);
2719 /* retreive the guid and store it locally */
2720 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2721 ZERO_STRUCT(guid);
2722 ads_pull_guid(ads, res, &guid);
2723 ads_msgfree(ads, res);
2724 store_printer_guid(printer->info_2, guid);
2725 win_rc = mod_a_printer(printer, 2);
2728 SAFE_FREE(prt_dn);
2729 return win_rc;
2732 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
2733 NT_PRINTER_INFO_LEVEL *printer)
2735 ADS_STATUS ads_rc;
2736 void *res;
2737 char *prt_dn = NULL;
2739 DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
2741 /* remove the printer from the directory */
2742 ads_rc = ads_find_printer_on_server(ads, &res,
2743 printer->info_2->sharename, global_myname());
2745 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2746 prt_dn = ads_get_dn(ads, res);
2747 ads_rc = ads_del_dn(ads, prt_dn);
2748 ads_memfree(ads, prt_dn);
2751 ads_msgfree(ads, res);
2752 return WERR_OK;
2755 /****************************************************************************
2756 * Publish a printer in the directory
2758 * @param snum describing printer service
2759 * @return WERROR indicating status of publishing
2760 ***************************************************************************/
2762 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2764 ADS_STATUS ads_rc;
2765 ADS_STRUCT *ads = NULL;
2766 NT_PRINTER_INFO_LEVEL *printer = NULL;
2767 WERROR win_rc;
2769 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2770 if (!W_ERROR_IS_OK(win_rc))
2771 goto done;
2773 switch (action) {
2774 case SPOOL_DS_PUBLISH:
2775 case SPOOL_DS_UPDATE:
2776 /* set the DsSpooler info and attributes */
2777 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
2778 win_rc = WERR_NOMEM;
2779 goto done;
2782 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2783 break;
2784 case SPOOL_DS_UNPUBLISH:
2785 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2786 break;
2787 default:
2788 win_rc = WERR_NOT_SUPPORTED;
2789 goto done;
2792 win_rc = mod_a_printer(printer, 2);
2793 if (!W_ERROR_IS_OK(win_rc)) {
2794 DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
2795 goto done;
2798 ads = ads_init(NULL, NULL, NULL);
2799 if (!ads) {
2800 DEBUG(3, ("ads_init() failed\n"));
2801 win_rc = WERR_SERVER_UNAVAILABLE;
2802 goto done;
2804 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2805 SAFE_FREE(ads->auth.password);
2806 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2807 NULL, NULL);
2809 /* ads_connect() will find the DC for us */
2810 ads_rc = ads_connect(ads);
2811 if (!ADS_ERR_OK(ads_rc)) {
2812 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2813 win_rc = WERR_ACCESS_DENIED;
2814 goto done;
2817 switch (action) {
2818 case SPOOL_DS_PUBLISH:
2819 case SPOOL_DS_UPDATE:
2820 win_rc = nt_printer_publish_ads(ads, printer);
2821 break;
2822 case SPOOL_DS_UNPUBLISH:
2823 win_rc = nt_printer_unpublish_ads(ads, printer);
2824 break;
2827 done:
2828 free_a_printer(&printer, 2);
2829 ads_destroy(&ads);
2830 return win_rc;
2833 WERROR check_published_printers(void)
2835 ADS_STATUS ads_rc;
2836 ADS_STRUCT *ads = NULL;
2837 int snum;
2838 int n_services = lp_numservices();
2839 NT_PRINTER_INFO_LEVEL *printer = NULL;
2841 ads = ads_init(NULL, NULL, NULL);
2842 if (!ads) {
2843 DEBUG(3, ("ads_init() failed\n"));
2844 return WERR_SERVER_UNAVAILABLE;
2846 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2847 SAFE_FREE(ads->auth.password);
2848 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2849 NULL, NULL);
2851 /* ads_connect() will find the DC for us */
2852 ads_rc = ads_connect(ads);
2853 if (!ADS_ERR_OK(ads_rc)) {
2854 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2855 ads_destroy(&ads);
2856 return WERR_ACCESS_DENIED;
2859 for (snum = 0; snum < n_services; snum++) {
2860 if (!(lp_snum_ok(snum) && lp_print_ok(snum)))
2861 continue;
2863 if (W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2,
2864 lp_servicename(snum))) &&
2865 (printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2866 nt_printer_publish_ads(ads, printer);
2868 free_a_printer(&printer, 2);
2871 ads_destroy(&ads);
2872 return WERR_OK;
2875 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2876 struct uuid *guid)
2878 NT_PRINTER_INFO_LEVEL *printer = NULL;
2879 REGVAL_CTR *ctr;
2880 REGISTRY_VALUE *guid_val;
2881 WERROR win_rc;
2882 int i;
2884 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2886 if (!W_ERROR_IS_OK(win_rc) ||
2887 !(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
2888 ((i = lookup_printerkey(&printer->info_2->data,
2889 SPOOL_DSSPOOLER_KEY)) < 0) ||
2890 !(ctr = &printer->info_2->data.keys[i].values) ||
2891 !(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2892 free_a_printer(&printer, 2);
2893 return False;
2896 if (regval_size(guid_val) == sizeof(struct uuid))
2897 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
2899 free_a_printer(&printer, 2);
2900 return True;
2902 #else
2903 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2905 return WERR_OK;
2908 WERROR check_published_printers(void)
2910 return WERR_OK;
2913 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2914 struct uuid *guid)
2916 return False;
2918 #endif /* HAVE_ADS */
2920 /****************************************************************************
2921 ***************************************************************************/
2923 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2925 NT_PRINTER_DATA *data;
2926 int i;
2927 int removed_keys = 0;
2928 int empty_slot;
2930 data = &p2->data;
2931 empty_slot = data->num_keys;
2933 if ( !key )
2934 return WERR_INVALID_PARAM;
2936 /* remove all keys */
2938 if ( !strlen(key) ) {
2939 for ( i=0; i<data->num_keys; i++ ) {
2940 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2941 data->keys[i].name));
2943 SAFE_FREE( data->keys[i].name );
2944 regval_ctr_destroy( &data->keys[i].values );
2947 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2948 p2->printername ));
2950 SAFE_FREE( data->keys );
2951 ZERO_STRUCTP( data );
2953 return WERR_OK;
2956 /* remove a specific key (and all subkeys) */
2958 for ( i=0; i<data->num_keys; i++ ) {
2959 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2960 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2961 data->keys[i].name));
2963 SAFE_FREE( data->keys[i].name );
2964 regval_ctr_destroy( &data->keys[i].values );
2966 /* mark the slot as empty */
2968 ZERO_STRUCTP( &data->keys[i] );
2972 /* find the first empty slot */
2974 for ( i=0; i<data->num_keys; i++ ) {
2975 if ( !data->keys[i].name ) {
2976 empty_slot = i;
2977 removed_keys++;
2978 break;
2982 if ( i == data->num_keys )
2983 /* nothing was removed */
2984 return WERR_INVALID_PARAM;
2986 /* move everything down */
2988 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2989 if ( data->keys[i].name ) {
2990 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2991 ZERO_STRUCTP( &data->keys[i] );
2992 empty_slot++;
2993 removed_keys++;
2997 /* update count */
2999 data->num_keys -= removed_keys;
3001 /* sanity check to see if anything is left */
3003 if ( !data->num_keys ) {
3004 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
3006 SAFE_FREE( data->keys );
3007 ZERO_STRUCTP( data );
3010 return WERR_OK;
3013 /****************************************************************************
3014 ***************************************************************************/
3016 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3018 WERROR result = WERR_OK;
3019 int key_index;
3021 /* we must have names on non-zero length */
3023 if ( !key || !*key|| !value || !*value )
3024 return WERR_INVALID_NAME;
3026 /* find the printer key first */
3028 key_index = lookup_printerkey( &p2->data, key );
3029 if ( key_index == -1 )
3030 return WERR_OK;
3032 /* make sure the value exists so we can return the correct error code */
3034 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
3035 return WERR_BADFILE;
3037 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
3039 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
3040 key, value ));
3042 return result;
3045 /****************************************************************************
3046 ***************************************************************************/
3048 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3049 uint32 type, uint8 *data, int real_len )
3051 WERROR result = WERR_OK;
3052 int key_index;
3054 /* we must have names on non-zero length */
3056 if ( !key || !*key|| !value || !*value )
3057 return WERR_INVALID_NAME;
3059 /* find the printer key first */
3061 key_index = lookup_printerkey( &p2->data, key );
3062 if ( key_index == -1 )
3063 key_index = add_new_printer_key( &p2->data, key );
3065 if ( key_index == -1 )
3066 return WERR_NOMEM;
3068 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3069 type, (const char *)data, real_len );
3071 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3072 key, value, type, real_len ));
3074 return result;
3077 /****************************************************************************
3078 ***************************************************************************/
3080 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3082 int key_index;
3084 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3085 return NULL;
3087 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3088 key, value ));
3090 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3093 /****************************************************************************
3094 Unpack a list of registry values frem the TDB
3095 ***************************************************************************/
3097 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3099 int len = 0;
3100 uint32 type;
3101 pstring string, valuename, keyname;
3102 char *str;
3103 int size;
3104 uint8 *data_p;
3105 REGISTRY_VALUE *regval_p;
3106 int key_index;
3108 /* add the "PrinterDriverData" key first for performance reasons */
3110 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3112 /* loop and unpack the rest of the registry values */
3114 while ( True ) {
3116 /* check to see if there are any more registry values */
3118 regval_p = NULL;
3119 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3120 if ( !regval_p )
3121 break;
3123 /* unpack the next regval */
3125 len += tdb_unpack(buf+len, buflen-len, "fdB",
3126 string,
3127 &type,
3128 &size,
3129 &data_p);
3132 * break of the keyname from the value name.
3133 * Valuenames can have embedded '\'s so be careful.
3134 * only support one level of keys. See the
3135 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3136 * -- jerry
3139 str = strchr_m( string, '\\');
3141 /* Put in "PrinterDriverData" is no key specified */
3143 if ( !str ) {
3144 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3145 pstrcpy( valuename, string );
3147 else {
3148 *str = '\0';
3149 pstrcpy( keyname, string );
3150 pstrcpy( valuename, str+1 );
3153 /* see if we need a new key */
3155 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3156 key_index = add_new_printer_key( printer_data, keyname );
3158 if ( key_index == -1 ) {
3159 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3160 keyname));
3161 break;
3164 /* add the new value */
3166 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3168 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3170 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3173 return len;
3176 /****************************************************************************
3177 ***************************************************************************/
3179 static void map_to_os2_driver(fstring drivername)
3181 static BOOL initialised=False;
3182 static fstring last_from,last_to;
3183 char *mapfile = lp_os2_driver_map();
3184 char **lines = NULL;
3185 int numlines = 0;
3186 int i;
3188 if (!strlen(drivername))
3189 return;
3191 if (!*mapfile)
3192 return;
3194 if (!initialised) {
3195 *last_from = *last_to = 0;
3196 initialised = True;
3199 if (strequal(drivername,last_from)) {
3200 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3201 fstrcpy(drivername,last_to);
3202 return;
3205 lines = file_lines_load(mapfile, &numlines);
3206 if (numlines == 0) {
3207 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3208 return;
3211 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3213 for( i = 0; i < numlines; i++) {
3214 char *nt_name = lines[i];
3215 char *os2_name = strchr(nt_name,'=');
3217 if (!os2_name)
3218 continue;
3220 *os2_name++ = 0;
3222 while (isspace(*nt_name))
3223 nt_name++;
3225 if (!*nt_name || strchr("#;",*nt_name))
3226 continue;
3229 int l = strlen(nt_name);
3230 while (l && isspace(nt_name[l-1])) {
3231 nt_name[l-1] = 0;
3232 l--;
3236 while (isspace(*os2_name))
3237 os2_name++;
3240 int l = strlen(os2_name);
3241 while (l && isspace(os2_name[l-1])) {
3242 os2_name[l-1] = 0;
3243 l--;
3247 if (strequal(nt_name,drivername)) {
3248 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3249 fstrcpy(last_from,drivername);
3250 fstrcpy(last_to,os2_name);
3251 fstrcpy(drivername,os2_name);
3252 file_lines_free(lines);
3253 return;
3257 file_lines_free(lines);
3260 /****************************************************************************
3261 Get a default printer info 2 struct.
3262 ****************************************************************************/
3263 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char* sharename)
3265 int snum;
3266 NT_PRINTER_INFO_LEVEL_2 info;
3268 ZERO_STRUCT(info);
3270 snum = lp_servicenumber(sharename);
3272 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3273 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3274 servername, sharename);
3275 fstrcpy(info.sharename, sharename);
3276 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3278 /* by setting the driver name to an empty string, a local NT admin
3279 can now run the **local** APW to install a local printer driver
3280 for a Samba shared printer in 2.2. Without this, drivers **must** be
3281 installed on the Samba server for NT clients --jerry */
3282 #if 0 /* JERRY --do not uncomment-- */
3283 if (!*info.drivername)
3284 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3285 #endif
3288 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3290 pstrcpy(info.comment, "");
3291 fstrcpy(info.printprocessor, "winprint");
3292 fstrcpy(info.datatype, "RAW");
3294 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3296 info.starttime = 0; /* Minutes since 12:00am GMT */
3297 info.untiltime = 0; /* Minutes since 12:00am GMT */
3298 info.priority = 1;
3299 info.default_priority = 1;
3300 info.setuptime = (uint32)time(NULL);
3303 * I changed this as I think it is better to have a generic
3304 * DEVMODE than to crash Win2k explorer.exe --jerry
3305 * See the HP Deskjet 990c Win2k drivers for an example.
3307 * However the default devmode appears to cause problems
3308 * with the HP CLJ 8500 PCL driver. Hence the addition of
3309 * the "default devmode" parameter --jerry 22/01/2002
3312 if (lp_default_devmode(snum)) {
3313 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3314 goto fail;
3316 else {
3317 info.devmode = NULL;
3320 /* This will get the current RPC talloc context, but we should be
3321 passing this as a parameter... fixme... JRA ! */
3323 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3324 goto fail;
3326 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3327 if (! *info_ptr) {
3328 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3329 goto fail;
3332 return WERR_OK;
3334 fail:
3335 if (info.devmode)
3336 free_nt_devicemode(&info.devmode);
3337 return WERR_ACCESS_DENIED;
3340 /****************************************************************************
3341 ****************************************************************************/
3342 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *servername, const char *sharename)
3344 pstring key;
3345 NT_PRINTER_INFO_LEVEL_2 info;
3346 int len = 0;
3347 int snum = lp_servicenumber(sharename);
3348 TDB_DATA kbuf, dbuf;
3349 fstring printername;
3350 char adevice[MAXDEVICENAME];
3352 ZERO_STRUCT(info);
3354 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3356 kbuf.dptr = key;
3357 kbuf.dsize = strlen(key)+1;
3359 dbuf = tdb_fetch(tdb_printers, kbuf);
3360 if (!dbuf.dptr)
3361 return get_a_printer_2_default(info_ptr, servername, sharename);
3363 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3364 &info.attributes,
3365 &info.priority,
3366 &info.default_priority,
3367 &info.starttime,
3368 &info.untiltime,
3369 &info.status,
3370 &info.cjobs,
3371 &info.averageppm,
3372 &info.changeid,
3373 &info.c_setprinter,
3374 &info.setuptime,
3375 info.servername,
3376 info.printername,
3377 info.sharename,
3378 info.portname,
3379 info.drivername,
3380 info.comment,
3381 info.location,
3382 info.sepfile,
3383 info.printprocessor,
3384 info.datatype,
3385 info.parameters);
3387 /* Samba has to have shared raw drivers. */
3388 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3389 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3391 /* Restore the stripped strings. */
3392 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", servername);
3394 if ( lp_force_printername(snum) )
3395 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, sharename );
3396 else
3397 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", servername, info.printername);
3399 fstrcpy(info.printername, printername);
3401 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3404 * Some client drivers freak out if there is a NULL devmode
3405 * (probably the driver is not checking before accessing
3406 * the devmode pointer) --jerry
3408 * See comments in get_a_printer_2_default()
3411 if (lp_default_devmode(snum) && !info.devmode) {
3412 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3413 printername));
3414 info.devmode = construct_nt_devicemode(printername);
3417 slprintf( adevice, sizeof(adevice), "%s", info.printername );
3418 if (info.devmode) {
3419 fstrcpy(info.devmode->devicename, adevice);
3422 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3424 /* This will get the current RPC talloc context, but we should be
3425 passing this as a parameter... fixme... JRA ! */
3427 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3429 /* Fix for OS/2 drivers. */
3431 if (get_remote_arch() == RA_OS2)
3432 map_to_os2_driver(info.drivername);
3434 SAFE_FREE(dbuf.dptr);
3435 *info_ptr=memdup(&info, sizeof(info));
3437 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3438 sharename, info.printername, info.drivername));
3440 return WERR_OK;
3443 /****************************************************************************
3444 Debugging function, dump at level 6 the struct in the logs.
3445 ****************************************************************************/
3446 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3448 uint32 result;
3449 NT_PRINTER_INFO_LEVEL_2 *info2;
3451 DEBUG(106,("Dumping printer at level [%d]\n", level));
3453 switch (level) {
3454 case 2:
3456 if (printer->info_2 == NULL)
3457 result=5;
3458 else
3460 info2=printer->info_2;
3462 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3463 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3464 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3465 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3466 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3467 DEBUGADD(106,("status:[%d]\n", info2->status));
3468 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3469 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3470 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3471 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3472 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3474 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3475 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3476 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3477 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3478 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3479 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3480 DEBUGADD(106,("location:[%s]\n", info2->location));
3481 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3482 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3483 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3484 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3485 result=0;
3487 break;
3489 default:
3490 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3491 result=1;
3492 break;
3495 return result;
3498 /****************************************************************************
3499 Update the changeid time.
3500 This is SO NASTY as some drivers need this to change, others need it
3501 static. This value will change every second, and I must hope that this
3502 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3503 UTAH ! JRA.
3504 ****************************************************************************/
3506 static uint32 rev_changeid(void)
3508 struct timeval tv;
3510 get_process_uptime(&tv);
3512 #if 1 /* JERRY */
3513 /* Return changeid as msec since spooler restart */
3514 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3515 #else
3517 * This setting seems to work well but is too untested
3518 * to replace the above calculation. Left in for experiementation
3519 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3521 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3522 #endif
3525 /********************************************************************
3526 Send a message to all smbds about the printer that just changed
3527 ********************************************************************/
3529 static BOOL send_printer_mod_msg( char* printername )
3531 int len = strlen(printername);
3533 if (!len)
3534 return False;
3536 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3537 printername));
3539 /* spam everyone that we just changed this printer */
3541 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3543 return True;
3547 * The function below are the high level ones.
3548 * only those ones must be called from the spoolss code.
3549 * JFM.
3552 /****************************************************************************
3553 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3554 ****************************************************************************/
3556 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3558 WERROR result;
3560 dump_a_printer(printer, level);
3563 * invalidate cache for all open handles to this printer.
3564 * cache for a given handle will be updated on the next
3565 * get_a_printer()
3568 invalidate_printer_hnd_cache( printer->info_2->sharename );
3569 send_printer_mod_msg( printer->info_2->sharename );
3571 switch (level) {
3572 case 2:
3575 * Update the changestamp. Emperical tests show that the
3576 * ChangeID is always updated,but c_setprinter is
3577 * global spooler variable (not per printer).
3580 /* ChangeID **must** be increasing over the lifetime
3581 of client's spoolss service in order for the
3582 client's cache to show updates */
3584 printer->info_2->changeid = rev_changeid();
3587 * Because one day someone will ask:
3588 * NT->NT An admin connection to a remote
3589 * printer show changes imeediately in
3590 * the properities dialog
3592 * A non-admin connection will only show the
3593 * changes after viewing the properites page
3594 * 2 times. Seems to be related to a
3595 * race condition in the client between the spooler
3596 * updating the local cache and the Explorer.exe GUI
3597 * actually displaying the properties.
3599 * This is fixed in Win2k. admin/non-admin
3600 * connections both display changes immediately.
3602 * 14/12/01 --jerry
3605 result=update_a_printer_2(printer->info_2);
3607 break;
3609 default:
3610 result=WERR_UNKNOWN_LEVEL;
3611 break;
3614 return result;
3617 /****************************************************************************
3618 Initialize printer devmode & data with previously saved driver init values.
3619 ****************************************************************************/
3621 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3623 int len = 0;
3624 pstring key;
3625 TDB_DATA kbuf, dbuf;
3626 NT_PRINTER_INFO_LEVEL_2 info;
3629 ZERO_STRUCT(info);
3632 * Delete any printer data 'values' already set. When called for driver
3633 * replace, there will generally be some, but during an add printer, there
3634 * should not be any (if there are delete them).
3637 delete_all_printer_data( info_ptr, "" );
3639 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3641 kbuf.dptr = key;
3642 kbuf.dsize = strlen(key)+1;
3644 dbuf = tdb_fetch(tdb_drivers, kbuf);
3645 if (!dbuf.dptr) {
3647 * When changing to a driver that has no init info in the tdb, remove
3648 * the previous drivers init info and leave the new on blank.
3650 free_nt_devicemode(&info_ptr->devmode);
3651 return False;
3655 * Get the saved DEVMODE..
3658 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3661 * The saved DEVMODE contains the devicename from the printer used during
3662 * the initialization save. Change it to reflect the new printer.
3665 if ( info.devmode ) {
3666 ZERO_STRUCT(info.devmode->devicename);
3667 fstrcpy(info.devmode->devicename, info_ptr->printername);
3671 * NT/2k does not change out the entire DeviceMode of a printer
3672 * when changing the driver. Only the driverextra, private, &
3673 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3675 * Later examination revealed that Windows NT/2k does reset the
3676 * the printer's device mode, bit **only** when you change a
3677 * property of the device mode such as the page orientation.
3678 * --jerry
3682 /* Bind the saved DEVMODE to the new the printer */
3684 free_nt_devicemode(&info_ptr->devmode);
3685 info_ptr->devmode = info.devmode;
3687 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3688 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3690 /* Add the printer data 'values' to the new printer */
3692 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3695 SAFE_FREE(dbuf.dptr);
3697 return True;
3700 /****************************************************************************
3701 Initialize printer devmode & data with previously saved driver init values.
3702 When a printer is created using AddPrinter, the drivername bound to the
3703 printer is used to lookup previously saved driver initialization info, which
3704 is bound to the new printer.
3705 ****************************************************************************/
3707 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3709 BOOL result = False;
3711 switch (level) {
3712 case 2:
3713 result = set_driver_init_2(printer->info_2);
3714 break;
3716 default:
3717 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3718 level));
3719 break;
3722 return result;
3725 /****************************************************************************
3726 Delete driver init data stored for a specified driver
3727 ****************************************************************************/
3729 BOOL del_driver_init(char *drivername)
3731 pstring key;
3732 TDB_DATA kbuf;
3734 if (!drivername || !*drivername) {
3735 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3736 return False;
3739 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3741 kbuf.dptr = key;
3742 kbuf.dsize = strlen(key)+1;
3744 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3746 return (tdb_delete(tdb_drivers, kbuf) == 0);
3749 /****************************************************************************
3750 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3751 in the tdb. Note: this is different from the driver entry and the printer
3752 entry. There should be a single driver init entry for each driver regardless
3753 of whether it was installed from NT or 2K. Technically, they should be
3754 different, but they work out to the same struct.
3755 ****************************************************************************/
3757 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3759 pstring key;
3760 char *buf;
3761 int buflen, len, ret;
3762 TDB_DATA kbuf, dbuf;
3764 buf = NULL;
3765 buflen = 0;
3767 again:
3768 len = 0;
3769 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3771 len += pack_values( &info->data, buf+len, buflen-len );
3773 if (buflen < len) {
3774 char *tb;
3776 tb = (char *)Realloc(buf, len);
3777 if (!tb) {
3778 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3779 ret = -1;
3780 goto done;
3782 else
3783 buf = tb;
3784 buflen = len;
3785 goto again;
3788 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3790 kbuf.dptr = key;
3791 kbuf.dsize = strlen(key)+1;
3792 dbuf.dptr = buf;
3793 dbuf.dsize = len;
3795 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3797 done:
3798 if (ret == -1)
3799 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3801 SAFE_FREE(buf);
3803 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3804 info->sharename, info->drivername));
3806 return ret;
3809 /****************************************************************************
3810 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3811 ****************************************************************************/
3813 static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3815 uint32 result;
3817 dump_a_printer(printer, level);
3819 switch (level) {
3820 case 2:
3821 result = update_driver_init_2(printer->info_2);
3822 break;
3823 default:
3824 result = 1;
3825 break;
3828 return result;
3831 /****************************************************************************
3832 Convert the printer data value, a REG_BINARY array, into an initialization
3833 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3834 got to keep the endians happy :).
3835 ****************************************************************************/
3837 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3839 BOOL result = False;
3840 prs_struct ps;
3841 DEVICEMODE devmode;
3843 ZERO_STRUCT(devmode);
3845 prs_init(&ps, 0, ctx, UNMARSHALL);
3846 ps.data_p = (char *)data;
3847 ps.buffer_size = data_len;
3849 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3850 result = convert_devicemode("", &devmode, &nt_devmode);
3851 else
3852 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3854 return result;
3857 /****************************************************************************
3858 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3860 1. Use the driver's config DLL to this UNC printername and:
3861 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3862 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3863 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3865 The last step triggers saving the "driver initialization" information for
3866 this printer into the tdb. Later, new printers that use this driver will
3867 have this initialization information bound to them. This simulates the
3868 driver initialization, as if it had run on the Samba server (as it would
3869 have done on NT).
3871 The Win32 client side code requirement sucks! But until we can run arbitrary
3872 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3874 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3875 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3876 about it and you will realize why. JRR 010720
3877 ****************************************************************************/
3879 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3881 WERROR status = WERR_OK;
3882 TALLOC_CTX *ctx = NULL;
3883 NT_DEVICEMODE *nt_devmode = NULL;
3884 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3887 * When the DEVMODE is already set on the printer, don't try to unpack it.
3889 DEBUG(8,("save_driver_init_2: Enter...\n"));
3891 if ( !printer->info_2->devmode && data_len ) {
3893 * Set devmode on printer info, so entire printer initialization can be
3894 * saved to tdb.
3897 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3898 return WERR_NOMEM;
3900 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3901 status = WERR_NOMEM;
3902 goto done;
3905 ZERO_STRUCTP(nt_devmode);
3908 * The DEVMODE is held in the 'data' component of the param in raw binary.
3909 * Convert it to to a devmode structure
3911 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3912 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3913 status = WERR_INVALID_PARAM;
3914 goto done;
3917 printer->info_2->devmode = nt_devmode;
3921 * Pack up and add (or update) the DEVMODE and any current printer data to
3922 * a 'driver init' element in the tdb
3926 if ( update_driver_init(printer, 2) != 0 ) {
3927 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3928 status = WERR_NOMEM;
3929 goto done;
3933 * If driver initialization info was successfully saved, set the current
3934 * printer to match it. This allows initialization of the current printer
3935 * as well as the driver.
3937 status = mod_a_printer(printer, 2);
3938 if (!W_ERROR_IS_OK(status)) {
3939 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3940 printer->info_2->printername));
3943 done:
3944 talloc_destroy(ctx);
3945 free_nt_devicemode( &nt_devmode );
3947 printer->info_2->devmode = tmp_devmode;
3949 return status;
3952 /****************************************************************************
3953 Update the driver init info (DEVMODE and specifics) for a printer
3954 ****************************************************************************/
3956 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3958 WERROR status = WERR_OK;
3960 switch (level) {
3961 case 2:
3962 status = save_driver_init_2( printer, data, data_len );
3963 break;
3964 default:
3965 status = WERR_UNKNOWN_LEVEL;
3966 break;
3969 return status;
3972 /****************************************************************************
3973 Deep copy a NT_PRINTER_DATA
3974 ****************************************************************************/
3976 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3978 int i, j, num_vals, new_key_index;
3979 REGVAL_CTR *src_key, *dst_key;
3981 if ( !dst || !src )
3982 return NT_STATUS_NO_MEMORY;
3984 for ( i=0; i<src->num_keys; i++ ) {
3986 /* create a new instance of the printerkey in the destination
3987 printer_data object */
3989 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3990 dst_key = &dst->keys[new_key_index].values;
3992 src_key = &src->keys[i].values;
3993 num_vals = regval_ctr_numvals( src_key );
3995 /* dup the printer entire printer key */
3997 for ( j=0; j<num_vals; j++ ) {
3998 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
4002 return NT_STATUS_OK;
4005 /****************************************************************************
4006 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
4007 Caller must free.
4008 ****************************************************************************/
4010 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
4012 NT_PRINTER_INFO_LEVEL_2 *copy;
4014 if ( !printer )
4015 return NULL;
4017 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
4018 return NULL;
4020 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
4022 /* malloc()'d members copied here */
4024 copy->devmode = dup_nt_devicemode( printer->devmode );
4026 ZERO_STRUCT( copy->data );
4027 copy_printer_data( &copy->data, &printer->data );
4029 /* this is talloc()'d; very ugly that we have a structure that
4030 is half malloc()'d and half talloc()'d but that is the way
4031 that the PRINTER_INFO stuff is written right now. --jerry */
4033 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
4035 return copy;
4038 /****************************************************************************
4039 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
4041 Previously the code had a memory allocation problem because it always
4042 used the TALLOC_CTX from the Printer_entry*. This context lasts
4043 as a long as the original handle is open. So if the client made a lot
4044 of getprinter[data]() calls, the memory usage would climb. Now we use
4045 a short lived TALLOC_CTX for printer_info_2 objects returned. We
4046 still use the Printer_entry->ctx for maintaining the cache copy though
4047 since that object must live as long as the handle by definition.
4048 --jerry
4050 ****************************************************************************/
4052 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
4053 const char *sharename)
4055 WERROR result;
4056 NT_PRINTER_INFO_LEVEL *printer = NULL;
4057 fstring servername;
4059 *pp_printer = NULL;
4061 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4063 switch (level) {
4064 case 2:
4065 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4066 DEBUG(0,("get_a_printer: malloc fail.\n"));
4067 return WERR_NOMEM;
4069 ZERO_STRUCTP(printer);
4071 if ( print_hnd )
4072 fstrcpy( servername, print_hnd->servername );
4073 else {
4074 fstrcpy( servername, "%L" );
4075 standard_sub_basic( "", servername, sizeof(servername)-1 );
4079 * check for cache first. A Printer handle cannot changed
4080 * to another printer object so we only check that the printer
4081 * is actually for a printer and that the printer_info pointer
4082 * is valid
4084 if ( print_hnd
4085 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4086 && print_hnd->printer_info )
4088 /* get_talloc_ctx() works here because we need a short
4089 lived talloc context */
4091 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4093 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4095 SAFE_FREE(printer);
4096 return WERR_NOMEM;
4099 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4101 *pp_printer = printer;
4102 result = WERR_OK;
4104 break;
4107 /* no cache for this handle; see if we can match one from another handle.
4108 Make sure to use a short lived talloc ctx */
4110 if ( print_hnd )
4111 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, servername, sharename);
4113 /* fail to disk if we don't have it with any open handle */
4115 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4116 result = get_a_printer_2(&printer->info_2, servername, sharename );
4118 /* we have a new printer now. Save it with this handle */
4120 if ( W_ERROR_IS_OK(result) ) {
4121 dump_a_printer(printer, level);
4123 /* save a copy in cache */
4124 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4125 if ( !print_hnd->printer_info )
4126 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
4128 if ( print_hnd->printer_info ) {
4129 /* make sure to use the handle's talloc ctx here since
4130 the printer_2 object must last until the handle is closed */
4132 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4134 /* don't fail the lookup just because the cache update failed */
4135 if ( !print_hnd->printer_info->info_2 )
4136 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4139 *pp_printer = printer;
4141 else
4142 SAFE_FREE(printer);
4144 break;
4146 default:
4147 result=WERR_UNKNOWN_LEVEL;
4148 break;
4151 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4153 return result;
4156 /****************************************************************************
4157 Deletes a NT_PRINTER_INFO_LEVEL struct.
4158 ****************************************************************************/
4160 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4162 uint32 result;
4163 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4165 DEBUG(104,("freeing a printer at level [%d]\n", level));
4167 if (printer == NULL)
4168 return 0;
4170 switch (level) {
4171 case 2:
4172 if (printer->info_2 != NULL) {
4173 free_nt_printer_info_level_2(&printer->info_2);
4174 result=0;
4175 } else
4176 result=4;
4177 break;
4179 default:
4180 result=1;
4181 break;
4184 SAFE_FREE(*pp_printer);
4185 return result;
4188 /****************************************************************************
4189 ****************************************************************************/
4190 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4192 uint32 result;
4193 DEBUG(104,("adding a printer at level [%d]\n", level));
4194 dump_a_printer_driver(driver, level);
4196 switch (level) {
4197 case 3:
4198 result=add_a_printer_driver_3(driver.info_3);
4199 break;
4201 case 6:
4202 result=add_a_printer_driver_6(driver.info_6);
4203 break;
4205 default:
4206 result=1;
4207 break;
4210 return result;
4212 /****************************************************************************
4213 ****************************************************************************/
4215 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4216 fstring drivername, const char *architecture, uint32 version)
4218 WERROR result;
4220 switch (level) {
4221 case 3:
4222 /* Sometime we just want any version of the driver */
4224 if ( version == DRIVER_ANY_VERSION ) {
4225 /* look for Win2k first and then for NT4 */
4226 result = get_a_printer_driver_3(&driver->info_3, drivername,
4227 architecture, 3);
4229 if ( !W_ERROR_IS_OK(result) ) {
4230 result = get_a_printer_driver_3( &driver->info_3,
4231 drivername, architecture, 2 );
4233 } else {
4234 result = get_a_printer_driver_3(&driver->info_3, drivername,
4235 architecture, version);
4237 break;
4239 default:
4240 result=W_ERROR(1);
4241 break;
4244 if (W_ERROR_IS_OK(result))
4245 dump_a_printer_driver(*driver, level);
4247 return result;
4250 /****************************************************************************
4251 ****************************************************************************/
4252 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4254 uint32 result;
4256 switch (level) {
4257 case 3:
4259 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4260 if (driver.info_3 != NULL)
4262 info3=driver.info_3;
4263 SAFE_FREE(info3->dependentfiles);
4264 ZERO_STRUCTP(info3);
4265 SAFE_FREE(info3);
4266 result=0;
4267 } else {
4268 result=4;
4270 break;
4272 case 6:
4274 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4275 if (driver.info_6 != NULL) {
4276 info6=driver.info_6;
4277 SAFE_FREE(info6->dependentfiles);
4278 SAFE_FREE(info6->previousnames);
4279 ZERO_STRUCTP(info6);
4280 SAFE_FREE(info6);
4281 result=0;
4282 } else {
4283 result=4;
4285 break;
4287 default:
4288 result=1;
4289 break;
4291 return result;
4295 /****************************************************************************
4296 Determine whether or not a particular driver is currently assigned
4297 to a printer
4298 ****************************************************************************/
4300 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4302 int snum;
4303 int n_services = lp_numservices();
4304 NT_PRINTER_INFO_LEVEL *printer = NULL;
4306 if ( !info_3 )
4307 return False;
4309 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4311 /* loop through the printers.tdb and check for the drivername */
4313 for (snum=0; snum<n_services; snum++) {
4314 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4315 continue;
4317 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4318 continue;
4320 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4321 free_a_printer( &printer, 2 );
4322 return True;
4325 free_a_printer( &printer, 2 );
4328 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4330 /* report that the driver is not in use by default */
4332 return False;
4336 /**********************************************************************
4337 Check to see if a ogiven file is in use by *info
4338 *********************************************************************/
4340 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4342 int i = 0;
4344 if ( !info )
4345 return False;
4347 if ( strequal(file, info->driverpath) )
4348 return True;
4350 if ( strequal(file, info->datafile) )
4351 return True;
4353 if ( strequal(file, info->configfile) )
4354 return True;
4356 if ( strequal(file, info->helpfile) )
4357 return True;
4359 /* see of there are any dependent files to examine */
4361 if ( !info->dependentfiles )
4362 return False;
4364 while ( *info->dependentfiles[i] ) {
4365 if ( strequal(file, info->dependentfiles[i]) )
4366 return True;
4367 i++;
4370 return False;
4374 /**********************************************************************
4375 Utility function to remove the dependent file pointed to by the
4376 input parameter from the list
4377 *********************************************************************/
4379 static void trim_dependent_file( fstring files[], int idx )
4382 /* bump everything down a slot */
4384 while( *files[idx+1] ) {
4385 fstrcpy( files[idx], files[idx+1] );
4386 idx++;
4389 *files[idx] = '\0';
4391 return;
4394 /**********************************************************************
4395 Check if any of the files used by src are also used by drv
4396 *********************************************************************/
4398 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4399 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4401 BOOL in_use = False;
4402 int i = 0;
4404 if ( !src || !drv )
4405 return False;
4407 /* check each file. Remove it from the src structure if it overlaps */
4409 if ( drv_file_in_use(src->driverpath, drv) ) {
4410 in_use = True;
4411 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4412 fstrcpy( src->driverpath, "" );
4415 if ( drv_file_in_use(src->datafile, drv) ) {
4416 in_use = True;
4417 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4418 fstrcpy( src->datafile, "" );
4421 if ( drv_file_in_use(src->configfile, drv) ) {
4422 in_use = True;
4423 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4424 fstrcpy( src->configfile, "" );
4427 if ( drv_file_in_use(src->helpfile, drv) ) {
4428 in_use = True;
4429 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4430 fstrcpy( src->helpfile, "" );
4433 /* are there any dependentfiles to examine? */
4435 if ( !src->dependentfiles )
4436 return in_use;
4438 while ( *src->dependentfiles[i] ) {
4439 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4440 in_use = True;
4441 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4442 trim_dependent_file( src->dependentfiles, i );
4443 } else
4444 i++;
4447 return in_use;
4450 /****************************************************************************
4451 Determine whether or not a particular driver files are currently being
4452 used by any other driver.
4454 Return value is True if any files were in use by other drivers
4455 and False otherwise.
4457 Upon return, *info has been modified to only contain the driver files
4458 which are not in use
4459 ****************************************************************************/
4461 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4463 int i;
4464 int ndrivers;
4465 uint32 version;
4466 fstring *list = NULL;
4467 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4469 if ( !info )
4470 return False;
4472 version = info->cversion;
4474 /* loop over all driver versions */
4476 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4478 /* get the list of drivers */
4480 list = NULL;
4481 ndrivers = get_ntdrivers(&list, info->environment, version);
4483 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4484 ndrivers, info->environment, version));
4486 /* check each driver for overlap in files */
4488 for (i=0; i<ndrivers; i++) {
4489 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4491 ZERO_STRUCT(driver);
4493 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4494 SAFE_FREE(list);
4495 return True;
4498 /* check if d2 uses any files from d1 */
4499 /* only if this is a different driver than the one being deleted */
4501 if ( !strequal(info->name, driver.info_3->name) ) {
4502 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4503 free_a_printer_driver(driver, 3);
4504 SAFE_FREE( list );
4505 return True;
4509 free_a_printer_driver(driver, 3);
4512 SAFE_FREE(list);
4514 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4516 driver.info_3 = info;
4518 if ( DEBUGLEVEL >= 20 )
4519 dump_a_printer_driver( driver, 3 );
4521 return False;
4524 /****************************************************************************
4525 Actually delete the driver files. Make sure that
4526 printer_driver_files_in_use() return False before calling
4527 this.
4528 ****************************************************************************/
4530 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4532 int i = 0;
4533 char *s;
4534 connection_struct *conn;
4535 DATA_BLOB null_pw;
4536 NTSTATUS nt_status;
4537 fstring res_type;
4538 BOOL bad_path;
4539 SMB_STRUCT_STAT st;
4541 if ( !info_3 )
4542 return False;
4544 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4547 * Connect to the print$ share under the same account as the
4548 * user connected to the rpc pipe. Note we must be root to
4549 * do this.
4552 null_pw = data_blob( NULL, 0 );
4553 fstrcpy(res_type, "A:");
4554 become_root();
4555 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4556 unbecome_root();
4558 if ( !conn ) {
4559 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4560 return False;
4563 /* Save who we are - we are temporarily becoming the connection user. */
4565 if ( !become_user(conn, conn->vuid) ) {
4566 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4567 return False;
4570 /* now delete the files; must strip the '\print$' string from
4571 fron of path */
4573 if ( *info_3->driverpath ) {
4574 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4575 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4576 DEBUG(10,("deleting driverfile [%s]\n", s));
4577 unlink_internals(conn, 0, s);
4581 if ( *info_3->configfile ) {
4582 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4583 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4584 DEBUG(10,("deleting configfile [%s]\n", s));
4585 unlink_internals(conn, 0, s);
4589 if ( *info_3->datafile ) {
4590 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4591 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4592 DEBUG(10,("deleting datafile [%s]\n", s));
4593 unlink_internals(conn, 0, s);
4597 if ( *info_3->helpfile ) {
4598 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4599 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4600 DEBUG(10,("deleting helpfile [%s]\n", s));
4601 unlink_internals(conn, 0, s);
4605 /* check if we are done removing files */
4607 if ( info_3->dependentfiles ) {
4608 while ( *info_3->dependentfiles[i] ) {
4609 char *file;
4611 /* bypass the "\print$" portion of the path */
4613 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4614 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4615 DEBUG(10,("deleting dependent file [%s]\n", file));
4616 unlink_internals(conn, 0, file );
4619 i++;
4623 unbecome_user();
4625 return True;
4628 /****************************************************************************
4629 Remove a printer driver from the TDB. This assumes that the the driver was
4630 previously looked up.
4631 ***************************************************************************/
4633 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4634 uint32 version, BOOL delete_files )
4636 pstring key;
4637 const char *arch;
4638 TDB_DATA kbuf, dbuf;
4639 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4641 /* delete the tdb data first */
4643 arch = get_short_archi(info_3->environment);
4644 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4645 arch, version, info_3->name);
4647 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4648 key, delete_files ? "TRUE" : "FALSE" ));
4650 ctr.info_3 = info_3;
4651 dump_a_printer_driver( ctr, 3 );
4653 kbuf.dptr=key;
4654 kbuf.dsize=strlen(key)+1;
4656 /* check if the driver actually exists for this environment */
4658 dbuf = tdb_fetch( tdb_drivers, kbuf );
4659 if ( !dbuf.dptr ) {
4660 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4661 return WERR_UNKNOWN_PRINTER_DRIVER;
4664 SAFE_FREE( dbuf.dptr );
4666 /* ok... the driver exists so the delete should return success */
4668 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4669 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4670 return WERR_ACCESS_DENIED;
4674 * now delete any associated files if delete_files == True
4675 * even if this part failes, we return succes because the
4676 * driver doesn not exist any more
4679 if ( delete_files )
4680 delete_driver_files( info_3, user );
4683 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4685 return WERR_OK;
4688 /****************************************************************************
4689 Store a security desc for a printer.
4690 ****************************************************************************/
4692 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4694 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4695 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4696 prs_struct ps;
4697 TALLOC_CTX *mem_ctx = NULL;
4698 fstring key;
4699 WERROR status;
4701 mem_ctx = talloc_init("nt_printing_setsec");
4702 if (mem_ctx == NULL)
4703 return WERR_NOMEM;
4705 /* The old owner and group sids of the security descriptor are not
4706 present when new ACEs are added or removed by changing printer
4707 permissions through NT. If they are NULL in the new security
4708 descriptor then copy them over from the old one. */
4710 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4711 DOM_SID *owner_sid, *group_sid;
4712 SEC_ACL *dacl, *sacl;
4713 SEC_DESC *psd = NULL;
4714 size_t size;
4716 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4718 /* Pick out correct owner and group sids */
4720 owner_sid = secdesc_ctr->sec->owner_sid ?
4721 secdesc_ctr->sec->owner_sid :
4722 old_secdesc_ctr->sec->owner_sid;
4724 group_sid = secdesc_ctr->sec->grp_sid ?
4725 secdesc_ctr->sec->grp_sid :
4726 old_secdesc_ctr->sec->grp_sid;
4728 dacl = secdesc_ctr->sec->dacl ?
4729 secdesc_ctr->sec->dacl :
4730 old_secdesc_ctr->sec->dacl;
4732 sacl = secdesc_ctr->sec->sacl ?
4733 secdesc_ctr->sec->sacl :
4734 old_secdesc_ctr->sec->sacl;
4736 /* Make a deep copy of the security descriptor */
4738 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4739 owner_sid, group_sid,
4740 sacl,
4741 dacl,
4742 &size);
4744 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4747 if (!new_secdesc_ctr) {
4748 new_secdesc_ctr = secdesc_ctr;
4751 /* Store the security descriptor in a tdb */
4753 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4754 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4756 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4757 &ps, 1)) {
4758 status = WERR_BADFUNC;
4759 goto out;
4762 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4764 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4765 status = WERR_OK;
4766 } else {
4767 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4768 status = WERR_BADFUNC;
4771 /* Free malloc'ed memory */
4773 out:
4775 prs_mem_free(&ps);
4776 if (mem_ctx)
4777 talloc_destroy(mem_ctx);
4778 return status;
4781 /****************************************************************************
4782 Construct a default security descriptor buffer for a printer.
4783 ****************************************************************************/
4785 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4787 SEC_ACE ace[3];
4788 SEC_ACCESS sa;
4789 SEC_ACL *psa = NULL;
4790 SEC_DESC_BUF *sdb = NULL;
4791 SEC_DESC *psd = NULL;
4792 DOM_SID owner_sid;
4793 size_t sd_size;
4795 /* Create an ACE where Everyone is allowed to print */
4797 init_sec_access(&sa, PRINTER_ACE_PRINT);
4798 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4799 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4801 /* Make the security descriptor owned by the Administrators group
4802 on the PDC of the domain. */
4804 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4805 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4806 } else {
4808 /* Backup plan - make printer owned by admins.
4809 This should emulate a lanman printer as security
4810 settings can't be changed. */
4812 sid_copy(&owner_sid, get_global_sam_sid());
4813 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4816 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4817 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4818 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4819 SEC_ACE_FLAG_INHERIT_ONLY);
4821 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4822 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4823 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4825 /* The ACL revision number in rpc_secdesc.h differs from the one
4826 created by NT when setting ACE entries in printer
4827 descriptors. NT4 complains about the property being edited by a
4828 NT5 machine. */
4830 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4831 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4832 &owner_sid, NULL,
4833 NULL, psa, &sd_size);
4836 if (!psd) {
4837 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4838 return NULL;
4841 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4843 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4844 (unsigned int)sd_size));
4846 return sdb;
4849 /****************************************************************************
4850 Get a security desc for a printer.
4851 ****************************************************************************/
4853 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4855 prs_struct ps;
4856 fstring key;
4857 char *temp;
4859 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4860 printername = temp + 1;
4863 /* Fetch security descriptor from tdb */
4865 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4867 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4868 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4870 DEBUG(4,("using default secdesc for %s\n", printername));
4872 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4873 return False;
4876 /* Save default security descriptor for later */
4878 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4879 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4881 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4882 tdb_prs_store(tdb_printers, key, &ps);
4884 prs_mem_free(&ps);
4886 return True;
4889 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4890 this security descriptor has been created when winbindd was
4891 down. Take ownership of security descriptor. */
4893 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4894 DOM_SID owner_sid;
4896 /* Change sd owner to workgroup administrator */
4898 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4899 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4900 SEC_DESC *psd = NULL;
4901 size_t size;
4903 /* Create new sd */
4905 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4907 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4908 &owner_sid,
4909 (*secdesc_ctr)->sec->grp_sid,
4910 (*secdesc_ctr)->sec->sacl,
4911 (*secdesc_ctr)->sec->dacl,
4912 &size);
4914 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4916 /* Swap with other one */
4918 *secdesc_ctr = new_secdesc_ctr;
4920 /* Set it */
4922 nt_printing_setsec(printername, *secdesc_ctr);
4926 if (DEBUGLEVEL >= 10) {
4927 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4928 int i;
4930 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4931 printername, the_acl->num_aces));
4933 for (i = 0; i < the_acl->num_aces; i++) {
4934 fstring sid_str;
4936 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4938 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4939 the_acl->ace[i].type, the_acl->ace[i].flags,
4940 the_acl->ace[i].info.mask));
4944 prs_mem_free(&ps);
4945 return True;
4948 /* error code:
4949 0: everything OK
4950 1: level not implemented
4951 2: file doesn't exist
4952 3: can't allocate memory
4953 4: can't free memory
4954 5: non existant struct
4958 A printer and a printer driver are 2 different things.
4959 NT manages them separatelly, Samba does the same.
4960 Why ? Simply because it's easier and it makes sense !
4962 Now explanation: You have 3 printers behind your samba server,
4963 2 of them are the same make and model (laser A and B). But laser B
4964 has an 3000 sheet feeder and laser A doesn't such an option.
4965 Your third printer is an old dot-matrix model for the accounting :-).
4967 If the /usr/local/samba/lib directory (default dir), you will have
4968 5 files to describe all of this.
4970 3 files for the printers (1 by printer):
4971 NTprinter_laser A
4972 NTprinter_laser B
4973 NTprinter_accounting
4974 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4975 NTdriver_printer model X
4976 NTdriver_printer model Y
4978 jfm: I should use this comment for the text file to explain
4979 same thing for the forms BTW.
4980 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4984 /* Convert generic access rights to printer object specific access rights.
4985 It turns out that NT4 security descriptors use generic access rights and
4986 NT5 the object specific ones. */
4988 void map_printer_permissions(SEC_DESC *sd)
4990 int i;
4992 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4993 se_map_generic(&sd->dacl->ace[i].info.mask,
4994 &printer_generic_mapping);
4998 /****************************************************************************
4999 Check a user has permissions to perform the given operation. We use the
5000 permission constants defined in include/rpc_spoolss.h to check the various
5001 actions we perform when checking printer access.
5003 PRINTER_ACCESS_ADMINISTER:
5004 print_queue_pause, print_queue_resume, update_printer_sec,
5005 update_printer, spoolss_addprinterex_level_2,
5006 _spoolss_setprinterdata
5008 PRINTER_ACCESS_USE:
5009 print_job_start
5011 JOB_ACCESS_ADMINISTER:
5012 print_job_delete, print_job_pause, print_job_resume,
5013 print_queue_purge
5015 ****************************************************************************/
5016 BOOL print_access_check(struct current_user *user, int snum, int access_type)
5018 SEC_DESC_BUF *secdesc = NULL;
5019 uint32 access_granted;
5020 NTSTATUS status;
5021 BOOL result;
5022 const char *pname;
5023 TALLOC_CTX *mem_ctx = NULL;
5024 extern struct current_user current_user;
5026 /* If user is NULL then use the current_user structure */
5028 if (!user)
5029 user = &current_user;
5031 /* Always allow root or printer admins to do anything */
5033 if (user->uid == 0 ||
5034 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
5035 return True;
5038 /* Get printer name */
5040 pname = PRINTERNAME(snum);
5042 if (!pname || !*pname) {
5043 errno = EACCES;
5044 return False;
5047 /* Get printer security descriptor */
5049 if(!(mem_ctx = talloc_init("print_access_check"))) {
5050 errno = ENOMEM;
5051 return False;
5054 nt_printing_getsec(mem_ctx, pname, &secdesc);
5056 if (access_type == JOB_ACCESS_ADMINISTER) {
5057 SEC_DESC_BUF *parent_secdesc = secdesc;
5059 /* Create a child security descriptor to check permissions
5060 against. This is because print jobs are child objects
5061 objects of a printer. */
5063 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5065 /* Now this is the bit that really confuses me. The access
5066 type needs to be changed from JOB_ACCESS_ADMINISTER to
5067 PRINTER_ACCESS_ADMINISTER for this to work. Something
5068 to do with the child (job) object becoming like a
5069 printer?? -tpot */
5071 access_type = PRINTER_ACCESS_ADMINISTER;
5074 /* Check access */
5076 map_printer_permissions(secdesc->sec);
5078 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5079 &access_granted, &status);
5081 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5083 talloc_destroy(mem_ctx);
5085 if (!result)
5086 errno = EACCES;
5088 return result;
5091 /****************************************************************************
5092 Check the time parameters allow a print operation.
5093 *****************************************************************************/
5095 BOOL print_time_access_check(int snum)
5097 NT_PRINTER_INFO_LEVEL *printer = NULL;
5098 BOOL ok = False;
5099 time_t now = time(NULL);
5100 struct tm *t;
5101 uint32 mins;
5103 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5104 return False;
5106 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5107 ok = True;
5109 t = gmtime(&now);
5110 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5112 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5113 ok = True;
5115 free_a_printer(&printer, 2);
5117 if (!ok)
5118 errno = EACCES;
5120 return ok;
5123 /****************************************************************************
5124 Fill in the servername sent in the _spoolss_open_printer_ex() call
5125 ****************************************************************************/
5126 char* get_server_name( Printer_entry *printer )
5128 return printer->servername;