make sure we have a devmode before copying a string to the devicename; patch from...
[Samba.git] / source / printing / nt_printing.c
blob5b5b5885ab0bd9afac020cb3eab84767efcea560
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2003.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 STANDARD_MAPPING printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 STANDARD_MAPPING printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static const nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 struct table_node {
202 const char *long_archi;
203 const char *short_archi;
204 int version;
207 #define SPL_ARCH_WIN40 "WIN40"
208 #define SPL_ARCH_W32X86 "W32X86"
209 #define SPL_ARCH_W32MIPS "W32MIPS"
210 #define SPL_ARCH_W32ALPHA "W32ALPHA"
211 #define SPL_ARCH_W32PPC "W32PPC"
213 static const struct table_node archi_table[]= {
215 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
216 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
217 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
218 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
219 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
220 {NULL, "", -1 }
223 static BOOL upgrade_to_version_3(void)
225 TDB_DATA kbuf, newkey, dbuf;
227 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
229 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
230 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
232 dbuf = tdb_fetch(tdb_drivers, kbuf);
234 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
235 DEBUG(0,("upgrade_to_version_3:moving form\n"));
236 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
237 SAFE_FREE(dbuf.dptr);
238 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
239 return False;
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 SAFE_FREE(dbuf.dptr);
243 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244 return False;
248 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
249 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
250 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
251 SAFE_FREE(dbuf.dptr);
252 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
253 return False;
255 if (tdb_delete(tdb_drivers, kbuf) != 0) {
256 SAFE_FREE(dbuf.dptr);
257 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
258 return False;
262 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
263 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
264 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
265 SAFE_FREE(dbuf.dptr);
266 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
267 return False;
269 if (tdb_delete(tdb_drivers, kbuf) != 0) {
270 SAFE_FREE(dbuf.dptr);
271 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
272 return False;
276 SAFE_FREE(dbuf.dptr);
279 return True;
282 /****************************************************************************
283 Open the NT printing tdbs. Done once before fork().
284 ****************************************************************************/
286 BOOL nt_printing_init(void)
288 static pid_t local_pid;
289 const char *vstring = "INFO/version";
291 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
292 return True;
294 if (tdb_drivers)
295 tdb_close(tdb_drivers);
296 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
297 if (!tdb_drivers) {
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno) ));
300 return False;
303 if (tdb_printers)
304 tdb_close(tdb_printers);
305 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
306 if (!tdb_printers) {
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno) ));
309 return False;
312 if (tdb_forms)
313 tdb_close(tdb_forms);
314 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
315 if (!tdb_forms) {
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno) ));
318 return False;
321 local_pid = sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers, vstring, 0);
326 int32 vers_id;
328 /* Cope with byte-reversed older versions of the db. */
329 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
330 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
331 /* Written on a bigendian machine with old fetch_int code. Save as le. */
332 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
333 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
334 vers_id = NTDRIVERS_DATABASE_VERSION;
337 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
339 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
340 if (!upgrade_to_version_3())
341 return False;
342 } else
343 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
345 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
348 tdb_unlock_bystring(tdb_drivers, vstring);
350 update_c_setprinter(True);
353 * register callback to handle updating printers as new
354 * drivers are installed
357 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
360 * register callback to handle updating printer data
361 * when a driver is initialized
364 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
367 return True;
370 /*******************************************************************
371 tdb traversal function for counting printers.
372 ********************************************************************/
374 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
375 TDB_DATA data, void *context)
377 int *printer_count = (int*)context;
379 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
380 (*printer_count)++;
381 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
384 return 0;
387 /*******************************************************************
388 Update the spooler global c_setprinter. This variable is initialized
389 when the parent smbd starts with the number of existing printers. It
390 is monotonically increased by the current number of printers *after*
391 each add or delete printer RPC. Only Microsoft knows why... JRR020119
392 ********************************************************************/
394 uint32 update_c_setprinter(BOOL initialize)
396 int32 c_setprinter;
397 int32 printer_count = 0;
399 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
401 /* Traverse the tdb, counting the printers */
402 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
404 /* If initializing, set c_setprinter to current printers count
405 * otherwise, bump it by the current printer count
407 if (!initialize)
408 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
409 else
410 c_setprinter = printer_count;
412 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
413 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
415 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
417 return (uint32)c_setprinter;
420 /*******************************************************************
421 Get the spooler global c_setprinter, accounting for initialization.
422 ********************************************************************/
424 uint32 get_c_setprinter(void)
426 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
428 if (c_setprinter == (int32)-1)
429 c_setprinter = update_c_setprinter(True);
431 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
433 return (uint32)c_setprinter;
436 /****************************************************************************
437 Get builtin form struct list.
438 ****************************************************************************/
440 int get_builtin_ntforms(nt_forms_struct **list)
442 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
443 return sizeof(default_forms) / sizeof(default_forms[0]);
446 /****************************************************************************
447 get a builtin form struct
448 ****************************************************************************/
450 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
452 int i,count;
453 fstring form_name;
454 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
455 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
456 count = sizeof(default_forms) / sizeof(default_forms[0]);
457 for (i=0;i<count;i++) {
458 if (strequal(form_name,default_forms[i].name)) {
459 DEBUGADD(6,("Found builtin form %s \n", form_name));
460 memcpy(form,&default_forms[i],sizeof(*form));
461 break;
465 return (i !=count);
468 /****************************************************************************
469 get a form struct list
470 ****************************************************************************/
471 int get_ntforms(nt_forms_struct **list)
473 TDB_DATA kbuf, newkey, dbuf;
474 nt_forms_struct *tl;
475 nt_forms_struct form;
476 int ret;
477 int i;
478 int n = 0;
480 for (kbuf = tdb_firstkey(tdb_forms);
481 kbuf.dptr;
482 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
484 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
485 continue;
487 dbuf = tdb_fetch(tdb_forms, kbuf);
488 if (!dbuf.dptr)
489 continue;
491 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
492 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
493 &i, &form.flag, &form.width, &form.length, &form.left,
494 &form.top, &form.right, &form.bottom);
495 SAFE_FREE(dbuf.dptr);
496 if (ret != dbuf.dsize)
497 continue;
499 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
500 if (!tl) {
501 DEBUG(0,("get_ntforms: Realloc fail.\n"));
502 return 0;
504 *list = tl;
505 (*list)[n] = form;
506 n++;
510 return n;
513 /****************************************************************************
514 write a form struct list
515 ****************************************************************************/
516 int write_ntforms(nt_forms_struct **list, int number)
518 pstring buf, key;
519 int len;
520 TDB_DATA kbuf,dbuf;
521 int i;
523 for (i=0;i<number;i++) {
524 /* save index, so list is rebuilt in correct order */
525 len = tdb_pack(buf, sizeof(buf), "dddddddd",
526 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
527 (*list)[i].left, (*list)[i].top, (*list)[i].right,
528 (*list)[i].bottom);
529 if (len > sizeof(buf)) break;
530 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
531 kbuf.dsize = strlen(key)+1;
532 kbuf.dptr = key;
533 dbuf.dsize = len;
534 dbuf.dptr = buf;
535 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
538 return i;
541 /****************************************************************************
542 add a form struct at the end of the list
543 ****************************************************************************/
544 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
546 int n=0;
547 BOOL update;
548 fstring form_name;
549 nt_forms_struct *tl;
552 * NT tries to add forms even when
553 * they are already in the base
554 * only update the values if already present
557 update=False;
559 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
560 for (n=0; n<*count; n++) {
561 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
562 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
563 update=True;
564 break;
568 if (update==False) {
569 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
570 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
571 return False;
573 *list = tl;
574 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
575 (*count)++;
578 (*list)[n].flag=form->flags;
579 (*list)[n].width=form->size_x;
580 (*list)[n].length=form->size_y;
581 (*list)[n].left=form->left;
582 (*list)[n].top=form->top;
583 (*list)[n].right=form->right;
584 (*list)[n].bottom=form->bottom;
586 return True;
589 /****************************************************************************
590 Delete a named form struct.
591 ****************************************************************************/
593 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
595 pstring key;
596 TDB_DATA kbuf;
597 int n=0;
598 fstring form_name;
600 *ret = WERR_OK;
602 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
604 for (n=0; n<*count; n++) {
605 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
606 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
607 break;
611 if (n == *count) {
612 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
613 *ret = WERR_INVALID_PARAM;
614 return False;
617 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
618 kbuf.dsize = strlen(key)+1;
619 kbuf.dptr = key;
620 if (tdb_delete(tdb_forms, kbuf) != 0) {
621 *ret = WERR_NOMEM;
622 return False;
625 return True;
628 /****************************************************************************
629 Update a form struct.
630 ****************************************************************************/
632 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
634 int n=0;
635 fstring form_name;
636 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
638 DEBUG(106, ("[%s]\n", form_name));
639 for (n=0; n<count; n++) {
640 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
641 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
642 break;
645 if (n==count) return;
647 (*list)[n].flag=form->flags;
648 (*list)[n].width=form->size_x;
649 (*list)[n].length=form->size_y;
650 (*list)[n].left=form->left;
651 (*list)[n].top=form->top;
652 (*list)[n].right=form->right;
653 (*list)[n].bottom=form->bottom;
656 /****************************************************************************
657 Get the nt drivers list.
658 Traverse the database and look-up the matching names.
659 ****************************************************************************/
660 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
662 int total=0;
663 const char *short_archi;
664 fstring *fl;
665 pstring key;
666 TDB_DATA kbuf, newkey;
668 short_archi = get_short_archi(architecture);
669 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
671 for (kbuf = tdb_firstkey(tdb_drivers);
672 kbuf.dptr;
673 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
675 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
676 continue;
678 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
679 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
680 return -1;
682 else *list = fl;
684 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
685 total++;
688 return(total);
691 /****************************************************************************
692 function to do the mapping between the long architecture name and
693 the short one.
694 ****************************************************************************/
695 const char *get_short_archi(const char *long_archi)
697 int i=-1;
699 DEBUG(107,("Getting architecture dependant directory\n"));
700 do {
701 i++;
702 } while ( (archi_table[i].long_archi!=NULL ) &&
703 StrCaseCmp(long_archi, archi_table[i].long_archi) );
705 if (archi_table[i].long_archi==NULL) {
706 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
707 return NULL;
710 /* this might be client code - but shouldn't this be an fstrcpy etc? */
713 DEBUGADD(108,("index: [%d]\n", i));
714 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
715 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
717 return archi_table[i].short_archi;
720 /****************************************************************************
721 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
722 There are two case to be covered here: PE (Portable Executable) and NE (New
723 Executable) files. Both files support the same INFO structure, but PE files
724 store the signature in unicode, and NE files store it as !unicode.
725 returns -1 on error, 1 on version info found, and 0 on no version info found.
726 ****************************************************************************/
728 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
730 int i;
731 char *buf;
732 ssize_t byte_count;
734 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname, PE_HEADER_SIZE));
737 goto error_exit;
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
743 fname, byte_count));
744 goto no_version_info;
747 /* Is this really a DOS header? */
748 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751 goto no_version_info;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
757 fname, errno));
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info;
762 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
764 fname, byte_count));
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
771 int num_sections;
772 int section_table_bytes;
774 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
780 goto error_exit;
783 /* get the section table */
784 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
786 SAFE_FREE(buf);
787 if ((buf=malloc(section_table_bytes)) == NULL) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname, section_table_bytes));
790 goto error_exit;
793 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
795 fname, byte_count));
796 goto error_exit;
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i = 0; i < num_sections; i++) {
801 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
803 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
804 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
805 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
807 SAFE_FREE(buf);
808 if ((buf=malloc(section_bytes)) == NULL) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname, section_bytes));
811 goto error_exit;
814 /* Seek to the start of the .rsrc section info */
815 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
817 fname, errno));
818 goto error_exit;
821 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
823 fname, byte_count));
824 goto error_exit;
827 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
830 /* Align to next long address */
831 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
834 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
835 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname, *major, *minor,
839 (*major>>16)&0xffff, *major&0xffff,
840 (*minor>>16)&0xffff, *minor&0xffff));
841 SAFE_FREE(buf);
842 return 1;
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
851 SAFE_FREE(buf);
852 return 0;
854 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
855 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
860 goto error_exit;
863 /* Allocate a bit more space to speed up things */
864 SAFE_FREE(buf);
865 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname, PE_HEADER_SIZE));
868 goto error_exit;
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
878 for(i=0; i<byte_count; i++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf[i] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i>byte_count-VS_VERSION_INFO_SIZE) {
885 int bc;
887 memcpy(buf, &buf[i], byte_count-i);
888 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
889 (byte_count-i))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
892 fname, errno));
893 goto error_exit;
896 byte_count = bc + (byte_count - i);
897 if (byte_count<VS_VERSION_INFO_SIZE) break;
899 i = 0;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
909 sizeof(VS_SIGNATURE)) & 3;
910 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
912 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
913 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname, *major, *minor,
916 (*major>>16)&0xffff, *major&0xffff,
917 (*minor>>16)&0xffff, *minor&0xffff));
918 SAFE_FREE(buf);
919 return 1;
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
926 SAFE_FREE(buf);
927 return 0;
929 } else
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
934 no_version_info:
935 SAFE_FREE(buf);
936 return 0;
938 error_exit:
939 SAFE_FREE(buf);
940 return -1;
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
953 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
955 BOOL use_version = True;
956 pstring filepath;
958 uint32 new_major;
959 uint32 new_minor;
960 time_t new_create_time;
962 uint32 old_major;
963 uint32 old_minor;
964 time_t old_create_time;
966 int access_mode;
967 int action;
968 files_struct *fsp = NULL;
969 SMB_STRUCT_STAT st;
970 SMB_STRUCT_STAT stat_buf;
971 BOOL bad_path;
973 ZERO_STRUCT(st);
974 ZERO_STRUCT(stat_buf);
975 new_create_time = (time_t)0;
976 old_create_time = (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath, old_file);
981 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
983 fsp = open_file_shared(conn, filepath, &stat_buf,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY),
985 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
986 0, 0, &access_mode, &action);
987 if (!fsp) {
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
990 filepath, errno));
991 return True;
993 } else {
994 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
995 if (ret == -1) goto error_exit;
997 if (!ret) {
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
999 old_file));
1000 use_version = False;
1001 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1002 old_create_time = st.st_mtime;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1006 close_file(fsp, True);
1008 /* Get file version info (if available) for new file */
1009 pstrcpy(filepath, new_file);
1010 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1012 fsp = open_file_shared(conn, filepath, &stat_buf,
1013 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1014 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1015 0, 0, &access_mode, &action);
1016 if (!fsp) {
1017 /* New file not found, this shouldn't occur if the caller did its job */
1018 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1019 filepath, errno));
1020 goto error_exit;
1022 } else {
1023 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1024 if (ret == -1) goto error_exit;
1026 if (!ret) {
1027 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1028 new_file));
1029 use_version = False;
1030 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1031 new_create_time = st.st_mtime;
1032 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1035 close_file(fsp, True);
1037 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1038 /* Compare versions and choose the larger version number */
1039 if (new_major > old_major ||
1040 (new_major == old_major && new_minor > old_minor)) {
1042 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1043 return True;
1045 else {
1046 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1047 return False;
1050 } else {
1051 /* Compare modification time/dates and choose the newest time/date */
1052 if (new_create_time > old_create_time) {
1053 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1054 return True;
1056 else {
1057 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1058 return False;
1062 error_exit:
1063 if(fsp)
1064 close_file(fsp, True);
1065 return -1;
1068 /****************************************************************************
1069 Determine the correct cVersion associated with an architecture and driver
1070 ****************************************************************************/
1071 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1072 struct current_user *user, WERROR *perr)
1074 int cversion;
1075 int access_mode;
1076 int action;
1077 NTSTATUS nt_status;
1078 pstring driverpath;
1079 DATA_BLOB null_pw;
1080 fstring res_type;
1081 files_struct *fsp = NULL;
1082 BOOL bad_path;
1083 SMB_STRUCT_STAT st;
1084 connection_struct *conn;
1086 ZERO_STRUCT(st);
1088 *perr = WERR_INVALID_PARAM;
1090 /* If architecture is Windows 95/98/ME, the version is always 0. */
1091 if (strcmp(architecture, "WIN40") == 0) {
1092 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1093 *perr = WERR_OK;
1094 return 0;
1098 * Connect to the print$ share under the same account as the user connected
1099 * to the rpc pipe. Note we must still be root to do this.
1102 /* Null password is ok - we are already an authenticated user... */
1103 null_pw = data_blob(NULL, 0);
1104 fstrcpy(res_type, "A:");
1105 become_root();
1106 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1107 unbecome_root();
1109 if (conn == NULL) {
1110 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1111 *perr = ntstatus_to_werror(nt_status);
1112 return -1;
1115 /* We are temporarily becoming the connection user. */
1116 if (!become_user(conn, user->vuid)) {
1117 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1118 *perr = WERR_ACCESS_DENIED;
1119 return -1;
1122 /* Open the driver file (Portable Executable format) and determine the
1123 * deriver the cversion. */
1124 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1126 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1128 fsp = open_file_shared(conn, driverpath, &st,
1129 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1130 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1131 0, 0, &access_mode, &action);
1132 if (!fsp) {
1133 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1134 driverpath, errno));
1135 *perr = WERR_ACCESS_DENIED;
1136 goto error_exit;
1138 else {
1139 uint32 major;
1140 uint32 minor;
1141 int ret = get_file_version(fsp, driverpath, &major, &minor);
1142 if (ret == -1) goto error_exit;
1144 if (!ret) {
1145 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1146 goto error_exit;
1150 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1151 * for more details. Version in this case is not just the version of the
1152 * file, but the version in the sense of kernal mode (2) vs. user mode
1153 * (3) drivers. Other bits of the version fields are the version info.
1154 * JRR 010716
1156 cversion = major & 0x0000ffff;
1157 switch (cversion) {
1158 case 2: /* WinNT drivers */
1159 case 3: /* Win2K drivers */
1160 break;
1162 default:
1163 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1164 driverpath, cversion));
1165 goto error_exit;
1168 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1169 driverpath, major, minor));
1172 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1173 driverpath, cversion));
1175 close_file(fsp, True);
1176 close_cnum(conn, user->vuid);
1177 unbecome_user();
1178 *perr = WERR_OK;
1179 return cversion;
1182 error_exit:
1184 if(fsp)
1185 close_file(fsp, True);
1187 close_cnum(conn, user->vuid);
1188 unbecome_user();
1189 return -1;
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1195 struct current_user *user)
1197 const char *architecture;
1198 fstring new_name;
1199 char *p;
1200 int i;
1201 WERROR err;
1203 /* clean up the driver name.
1204 * we can get .\driver.dll
1205 * or worse c:\windows\system\driver.dll !
1207 /* using an intermediate string to not have overlaping memcpy()'s */
1208 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1209 fstrcpy(new_name, p+1);
1210 fstrcpy(driver->driverpath, new_name);
1213 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1214 fstrcpy(new_name, p+1);
1215 fstrcpy(driver->datafile, new_name);
1218 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1219 fstrcpy(new_name, p+1);
1220 fstrcpy(driver->configfile, new_name);
1223 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1224 fstrcpy(new_name, p+1);
1225 fstrcpy(driver->helpfile, new_name);
1228 if (driver->dependentfiles) {
1229 for (i=0; *driver->dependentfiles[i]; i++) {
1230 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1231 fstrcpy(new_name, p+1);
1232 fstrcpy(driver->dependentfiles[i], new_name);
1237 architecture = get_short_archi(driver->environment);
1239 /* jfm:7/16/2000 the client always sends the cversion=0.
1240 * The server should check which version the driver is by reading
1241 * the PE header of driver->driverpath.
1243 * For Windows 95/98 the version is 0 (so the value sent is correct)
1244 * For Windows NT (the architecture doesn't matter)
1245 * NT 3.1: cversion=0
1246 * NT 3.5/3.51: cversion=1
1247 * NT 4: cversion=2
1248 * NT2K: cversion=3
1250 if ((driver->cversion = get_correct_cversion( architecture,
1251 driver->driverpath, user, &err)) == -1)
1252 return err;
1254 return WERR_OK;
1257 /****************************************************************************
1258 ****************************************************************************/
1259 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1261 const char *architecture;
1262 fstring new_name;
1263 char *p;
1264 int i;
1265 WERROR err;
1267 /* clean up the driver name.
1268 * we can get .\driver.dll
1269 * or worse c:\windows\system\driver.dll !
1271 /* using an intermediate string to not have overlaping memcpy()'s */
1272 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1273 fstrcpy(new_name, p+1);
1274 fstrcpy(driver->driverpath, new_name);
1277 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1278 fstrcpy(new_name, p+1);
1279 fstrcpy(driver->datafile, new_name);
1282 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1283 fstrcpy(new_name, p+1);
1284 fstrcpy(driver->configfile, new_name);
1287 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1288 fstrcpy(new_name, p+1);
1289 fstrcpy(driver->helpfile, new_name);
1292 if (driver->dependentfiles) {
1293 for (i=0; *driver->dependentfiles[i]; i++) {
1294 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1295 fstrcpy(new_name, p+1);
1296 fstrcpy(driver->dependentfiles[i], new_name);
1301 architecture = get_short_archi(driver->environment);
1303 /* jfm:7/16/2000 the client always sends the cversion=0.
1304 * The server should check which version the driver is by reading
1305 * the PE header of driver->driverpath.
1307 * For Windows 95/98 the version is 0 (so the value sent is correct)
1308 * For Windows NT (the architecture doesn't matter)
1309 * NT 3.1: cversion=0
1310 * NT 3.5/3.51: cversion=1
1311 * NT 4: cversion=2
1312 * NT2K: cversion=3
1314 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1315 return err;
1317 return WERR_OK;
1320 /****************************************************************************
1321 ****************************************************************************/
1322 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1323 uint32 level, struct current_user *user)
1325 switch (level) {
1326 case 3:
1328 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1329 driver=driver_abstract.info_3;
1330 return clean_up_driver_struct_level_3(driver, user);
1332 case 6:
1334 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1335 driver=driver_abstract.info_6;
1336 return clean_up_driver_struct_level_6(driver, user);
1338 default:
1339 return WERR_INVALID_PARAM;
1343 /****************************************************************************
1344 This function sucks and should be replaced. JRA.
1345 ****************************************************************************/
1347 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1349 dst->cversion = src->version;
1351 fstrcpy( dst->name, src->name);
1352 fstrcpy( dst->environment, src->environment);
1353 fstrcpy( dst->driverpath, src->driverpath);
1354 fstrcpy( dst->datafile, src->datafile);
1355 fstrcpy( dst->configfile, src->configfile);
1356 fstrcpy( dst->helpfile, src->helpfile);
1357 fstrcpy( dst->monitorname, src->monitorname);
1358 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1359 dst->dependentfiles = src->dependentfiles;
1362 #if 0 /* Debugging function */
1364 static char* ffmt(unsigned char *c){
1365 int i;
1366 static char ffmt_str[17];
1368 for (i=0; i<16; i++) {
1369 if ((c[i] < ' ') || (c[i] > '~'))
1370 ffmt_str[i]='.';
1371 else
1372 ffmt_str[i]=c[i];
1374 ffmt_str[16]='\0';
1375 return ffmt_str;
1378 #endif
1380 /****************************************************************************
1381 ****************************************************************************/
1382 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1383 struct current_user *user, WERROR *perr)
1385 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1386 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1387 const char *architecture;
1388 pstring new_dir;
1389 pstring old_name;
1390 pstring new_name;
1391 DATA_BLOB null_pw;
1392 connection_struct *conn;
1393 NTSTATUS nt_status;
1394 pstring inbuf;
1395 pstring outbuf;
1396 fstring res_type;
1397 int ver = 0;
1398 int i;
1400 memset(inbuf, '\0', sizeof(inbuf));
1401 memset(outbuf, '\0', sizeof(outbuf));
1402 *perr = WERR_OK;
1404 if (level==3)
1405 driver=driver_abstract.info_3;
1406 else if (level==6) {
1407 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1408 driver = &converted_driver;
1409 } else {
1410 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1411 return False;
1414 architecture = get_short_archi(driver->environment);
1417 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1418 * Note we must be root to do this.
1421 null_pw = data_blob(NULL, 0);
1422 fstrcpy(res_type, "A:");
1423 become_root();
1424 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1425 unbecome_root();
1427 if (conn == NULL) {
1428 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1429 *perr = ntstatus_to_werror(nt_status);
1430 return False;
1434 * Save who we are - we are temporarily becoming the connection user.
1437 if (!become_user(conn, conn->vuid)) {
1438 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1439 return False;
1443 * make the directories version and version\driver_name
1444 * under the architecture directory.
1446 DEBUG(5,("Creating first directory\n"));
1447 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1448 mkdir_internal(conn, new_dir);
1450 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1451 * listed for this driver which has already been moved, skip it (note:
1452 * drivers may list the same file name several times. Then check if the
1453 * file already exists in archi\cversion\, if so, check that the version
1454 * info (or time stamps if version info is unavailable) is newer (or the
1455 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1456 * Otherwise, delete the file.
1458 * If a file is not moved to archi\cversion\ because of an error, all the
1459 * rest of the 'unmoved' driver files are removed from archi\. If one or
1460 * more of the driver's files was already moved to archi\cversion\, it
1461 * potentially leaves the driver in a partially updated state. Version
1462 * trauma will most likely occur if an client attempts to use any printer
1463 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1464 * done is appropriate... later JRR
1467 DEBUG(5,("Moving files now !\n"));
1469 if (driver->driverpath && strlen(driver->driverpath)) {
1470 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1471 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1472 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1473 NTSTATUS status;
1474 status = rename_internals(conn, new_name, old_name, True);
1475 if (!NT_STATUS_IS_OK(status)) {
1476 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1477 new_name, old_name));
1478 *perr = ntstatus_to_werror(status);
1479 unlink_internals(conn, 0, new_name);
1480 ver = -1;
1483 else
1484 unlink_internals(conn, 0, new_name);
1487 if (driver->datafile && strlen(driver->datafile)) {
1488 if (!strequal(driver->datafile, driver->driverpath)) {
1489 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1490 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1491 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1492 NTSTATUS status;
1493 status = rename_internals(conn, new_name, old_name, True);
1494 if (!NT_STATUS_IS_OK(status)) {
1495 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1496 new_name, old_name));
1497 *perr = ntstatus_to_werror(status);
1498 unlink_internals(conn, 0, new_name);
1499 ver = -1;
1502 else
1503 unlink_internals(conn, 0, new_name);
1507 if (driver->configfile && strlen(driver->configfile)) {
1508 if (!strequal(driver->configfile, driver->driverpath) &&
1509 !strequal(driver->configfile, driver->datafile)) {
1510 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1511 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1512 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1513 NTSTATUS status;
1514 status = rename_internals(conn, new_name, old_name, True);
1515 if (!NT_STATUS_IS_OK(status)) {
1516 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1517 new_name, old_name));
1518 *perr = ntstatus_to_werror(status);
1519 unlink_internals(conn, 0, new_name);
1520 ver = -1;
1523 else
1524 unlink_internals(conn, 0, new_name);
1528 if (driver->helpfile && strlen(driver->helpfile)) {
1529 if (!strequal(driver->helpfile, driver->driverpath) &&
1530 !strequal(driver->helpfile, driver->datafile) &&
1531 !strequal(driver->helpfile, driver->configfile)) {
1532 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1533 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1534 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1535 NTSTATUS status;
1536 status = rename_internals(conn, new_name, old_name, True);
1537 if (!NT_STATUS_IS_OK(status)) {
1538 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1539 new_name, old_name));
1540 *perr = ntstatus_to_werror(status);
1541 unlink_internals(conn, 0, new_name);
1542 ver = -1;
1545 else
1546 unlink_internals(conn, 0, new_name);
1550 if (driver->dependentfiles) {
1551 for (i=0; *driver->dependentfiles[i]; i++) {
1552 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1553 !strequal(driver->dependentfiles[i], driver->datafile) &&
1554 !strequal(driver->dependentfiles[i], driver->configfile) &&
1555 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1556 int j;
1557 for (j=0; j < i; j++) {
1558 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1559 goto NextDriver;
1563 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1564 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1565 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1566 NTSTATUS status;
1567 status = rename_internals(conn, new_name, old_name, True);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1570 new_name, old_name));
1571 *perr = ntstatus_to_werror(status);
1572 unlink_internals(conn, 0, new_name);
1573 ver = -1;
1576 else
1577 unlink_internals(conn, 0, new_name);
1579 NextDriver: ;
1583 close_cnum(conn, user->vuid);
1584 unbecome_user();
1586 return ver == -1 ? False : True;
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1593 int len, buflen;
1594 const char *architecture;
1595 pstring directory;
1596 fstring temp_name;
1597 pstring key;
1598 char *buf;
1599 int i, ret;
1600 TDB_DATA kbuf, dbuf;
1602 architecture = get_short_archi(driver->environment);
1604 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1605 * \\server is added in the rpc server layer.
1606 * It does make sense to NOT store the server's name in the printer TDB.
1609 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1611 /* .inf files do not always list a file for each of the four standard files.
1612 * Don't prepend a path to a null filename, or client claims:
1613 * "The server on which the printer resides does not have a suitable
1614 * <printer driver name> printer driver installed. Click OK if you
1615 * wish to install the driver on your local machine."
1617 if (strlen(driver->driverpath)) {
1618 fstrcpy(temp_name, driver->driverpath);
1619 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1622 if (strlen(driver->datafile)) {
1623 fstrcpy(temp_name, driver->datafile);
1624 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1627 if (strlen(driver->configfile)) {
1628 fstrcpy(temp_name, driver->configfile);
1629 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1632 if (strlen(driver->helpfile)) {
1633 fstrcpy(temp_name, driver->helpfile);
1634 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1637 if (driver->dependentfiles) {
1638 for (i=0; *driver->dependentfiles[i]; i++) {
1639 fstrcpy(temp_name, driver->dependentfiles[i]);
1640 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1644 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1646 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1648 buf = NULL;
1649 len = buflen = 0;
1651 again:
1652 len = 0;
1653 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1654 driver->cversion,
1655 driver->name,
1656 driver->environment,
1657 driver->driverpath,
1658 driver->datafile,
1659 driver->configfile,
1660 driver->helpfile,
1661 driver->monitorname,
1662 driver->defaultdatatype);
1664 if (driver->dependentfiles) {
1665 for (i=0; *driver->dependentfiles[i]; i++) {
1666 len += tdb_pack(buf+len, buflen-len, "f",
1667 driver->dependentfiles[i]);
1671 if (len != buflen) {
1672 char *tb;
1674 tb = (char *)Realloc(buf, len);
1675 if (!tb) {
1676 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1677 ret = -1;
1678 goto done;
1680 else buf = tb;
1681 buflen = len;
1682 goto again;
1686 kbuf.dptr = key;
1687 kbuf.dsize = strlen(key)+1;
1688 dbuf.dptr = buf;
1689 dbuf.dsize = len;
1691 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1693 done:
1694 if (ret)
1695 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1697 SAFE_FREE(buf);
1698 return ret;
1701 /****************************************************************************
1702 ****************************************************************************/
1703 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1705 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1707 ZERO_STRUCT(info3);
1708 info3.cversion = driver->version;
1709 fstrcpy(info3.name,driver->name);
1710 fstrcpy(info3.environment,driver->environment);
1711 fstrcpy(info3.driverpath,driver->driverpath);
1712 fstrcpy(info3.datafile,driver->datafile);
1713 fstrcpy(info3.configfile,driver->configfile);
1714 fstrcpy(info3.helpfile,driver->helpfile);
1715 fstrcpy(info3.monitorname,driver->monitorname);
1716 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1717 info3.dependentfiles = driver->dependentfiles;
1719 return add_a_printer_driver_3(&info3);
1723 /****************************************************************************
1724 ****************************************************************************/
1725 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1727 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1729 ZERO_STRUCT(info);
1731 fstrcpy(info.name, driver);
1732 fstrcpy(info.defaultdatatype, "RAW");
1734 fstrcpy(info.driverpath, "");
1735 fstrcpy(info.datafile, "");
1736 fstrcpy(info.configfile, "");
1737 fstrcpy(info.helpfile, "");
1739 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1740 return WERR_NOMEM;
1742 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1743 fstrcpy(info.dependentfiles[0], "");
1745 *info_ptr = memdup(&info, sizeof(info));
1747 return WERR_OK;
1750 /****************************************************************************
1751 ****************************************************************************/
1752 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1754 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1755 TDB_DATA kbuf, dbuf;
1756 const char *architecture;
1757 int len = 0;
1758 int i;
1759 pstring key;
1761 ZERO_STRUCT(driver);
1763 architecture = get_short_archi(arch);
1765 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1767 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1768 version = 0;
1770 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1772 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1774 kbuf.dptr = key;
1775 kbuf.dsize = strlen(key)+1;
1777 dbuf = tdb_fetch(tdb_drivers, kbuf);
1778 if (!dbuf.dptr)
1779 return WERR_UNKNOWN_PRINTER_DRIVER;
1781 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1782 &driver.cversion,
1783 driver.name,
1784 driver.environment,
1785 driver.driverpath,
1786 driver.datafile,
1787 driver.configfile,
1788 driver.helpfile,
1789 driver.monitorname,
1790 driver.defaultdatatype);
1792 i=0;
1793 while (len < dbuf.dsize) {
1794 fstring *tddfs;
1796 tddfs = (fstring *)Realloc(driver.dependentfiles,
1797 sizeof(fstring)*(i+2));
1798 if (tddfs == NULL) {
1799 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1800 break;
1802 else driver.dependentfiles = tddfs;
1804 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1805 &driver.dependentfiles[i]);
1806 i++;
1809 if (driver.dependentfiles != NULL)
1810 fstrcpy(driver.dependentfiles[i], "");
1812 SAFE_FREE(dbuf.dptr);
1814 if (len != dbuf.dsize) {
1815 SAFE_FREE(driver.dependentfiles);
1817 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1820 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1822 return WERR_OK;
1825 /****************************************************************************
1826 Debugging function, dump at level 6 the struct in the logs.
1827 ****************************************************************************/
1829 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1831 uint32 result;
1832 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1833 int i;
1835 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1837 switch (level)
1839 case 3:
1841 if (driver.info_3 == NULL)
1842 result=5;
1843 else {
1844 info3=driver.info_3;
1846 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1847 DEBUGADD(20,("name:[%s]\n", info3->name));
1848 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1849 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1850 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1851 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1852 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1853 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1854 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1856 for (i=0; info3->dependentfiles &&
1857 *info3->dependentfiles[i]; i++) {
1858 DEBUGADD(20,("dependentfile:[%s]\n",
1859 info3->dependentfiles[i]));
1861 result=0;
1863 break;
1865 default:
1866 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1867 result=1;
1868 break;
1871 return result;
1874 /****************************************************************************
1875 ****************************************************************************/
1876 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1878 int len = 0;
1880 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1882 if (!nt_devmode)
1883 return len;
1885 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1886 nt_devmode->devicename,
1887 nt_devmode->formname,
1889 nt_devmode->specversion,
1890 nt_devmode->driverversion,
1891 nt_devmode->size,
1892 nt_devmode->driverextra,
1893 nt_devmode->orientation,
1894 nt_devmode->papersize,
1895 nt_devmode->paperlength,
1896 nt_devmode->paperwidth,
1897 nt_devmode->scale,
1898 nt_devmode->copies,
1899 nt_devmode->defaultsource,
1900 nt_devmode->printquality,
1901 nt_devmode->color,
1902 nt_devmode->duplex,
1903 nt_devmode->yresolution,
1904 nt_devmode->ttoption,
1905 nt_devmode->collate,
1906 nt_devmode->logpixels,
1908 nt_devmode->fields,
1909 nt_devmode->bitsperpel,
1910 nt_devmode->pelswidth,
1911 nt_devmode->pelsheight,
1912 nt_devmode->displayflags,
1913 nt_devmode->displayfrequency,
1914 nt_devmode->icmmethod,
1915 nt_devmode->icmintent,
1916 nt_devmode->mediatype,
1917 nt_devmode->dithertype,
1918 nt_devmode->reserved1,
1919 nt_devmode->reserved2,
1920 nt_devmode->panningwidth,
1921 nt_devmode->panningheight,
1922 nt_devmode->private);
1925 if (nt_devmode->private) {
1926 len += tdb_pack(buf+len, buflen-len, "B",
1927 nt_devmode->driverextra,
1928 nt_devmode->private);
1931 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1933 return len;
1936 /****************************************************************************
1937 Pack all values in all printer keys
1938 ***************************************************************************/
1940 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1942 int len = 0;
1943 int i, j;
1944 REGISTRY_VALUE *val;
1945 REGVAL_CTR *val_ctr;
1946 pstring path;
1947 int num_values;
1949 if ( !data )
1950 return 0;
1952 /* loop over all keys */
1954 for ( i=0; i<data->num_keys; i++ ) {
1955 val_ctr = &data->keys[i].values;
1956 num_values = regval_ctr_numvals( val_ctr );
1958 /* loop over all values */
1960 for ( j=0; j<num_values; j++ ) {
1961 /* pathname should be stored as <key>\<value> */
1963 val = regval_ctr_specific_value( val_ctr, j );
1964 pstrcpy( path, data->keys[i].name );
1965 pstrcat( path, "\\" );
1966 pstrcat( path, regval_name(val) );
1968 len += tdb_pack(buf+len, buflen-len, "pPdB",
1969 val,
1970 path,
1971 regval_type(val),
1972 regval_size(val),
1973 regval_data_p(val) );
1978 /* terminator */
1980 len += tdb_pack(buf+len, buflen-len, "p", NULL);
1982 return len;
1986 /****************************************************************************
1987 Delete a printer - this just deletes the printer info file, any open
1988 handles are not affected.
1989 ****************************************************************************/
1991 uint32 del_a_printer(char *sharename)
1993 pstring key;
1994 TDB_DATA kbuf;
1996 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
1998 kbuf.dptr=key;
1999 kbuf.dsize=strlen(key)+1;
2001 tdb_delete(tdb_printers, kbuf);
2002 return 0;
2005 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2006 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2007 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2008 /****************************************************************************
2009 ****************************************************************************/
2010 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2012 pstring key;
2013 char *buf;
2014 int buflen, len;
2015 WERROR ret;
2016 TDB_DATA kbuf, dbuf;
2019 * in addprinter: no servername and the printer is the name
2020 * in setprinter: servername is \\server
2021 * and printer is \\server\\printer
2023 * Samba manages only local printers.
2024 * we currently don't support things like path=\\other_server\printer
2027 if (info->servername[0]!='\0') {
2028 trim_string(info->printername, info->servername, NULL);
2029 trim_char(info->printername, '\\', '\0');
2030 info->servername[0]='\0';
2034 * JFM: one day I'll forget.
2035 * below that's info->portname because that's the SAMBA sharename
2036 * and I made NT 'thinks' it's the portname
2037 * the info->sharename is the thing you can name when you add a printer
2038 * that's the short-name when you create shared printer for 95/98
2039 * So I've made a limitation in SAMBA: you can only have 1 printer model
2040 * behind a SAMBA share.
2043 buf = NULL;
2044 buflen = 0;
2046 again:
2047 len = 0;
2048 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2049 info->attributes,
2050 info->priority,
2051 info->default_priority,
2052 info->starttime,
2053 info->untiltime,
2054 info->status,
2055 info->cjobs,
2056 info->averageppm,
2057 info->changeid,
2058 info->c_setprinter,
2059 info->setuptime,
2060 info->servername,
2061 info->printername,
2062 info->sharename,
2063 info->portname,
2064 info->drivername,
2065 info->comment,
2066 info->location,
2067 info->sepfile,
2068 info->printprocessor,
2069 info->datatype,
2070 info->parameters);
2072 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2074 len += pack_values( &info->data, buf+len, buflen-len );
2076 if (buflen != len) {
2077 char *tb;
2079 tb = (char *)Realloc(buf, len);
2080 if (!tb) {
2081 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2082 ret = WERR_NOMEM;
2083 goto done;
2085 else buf = tb;
2086 buflen = len;
2087 goto again;
2091 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2093 kbuf.dptr = key;
2094 kbuf.dsize = strlen(key)+1;
2095 dbuf.dptr = buf;
2096 dbuf.dsize = len;
2098 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2100 done:
2101 if (!W_ERROR_IS_OK(ret))
2102 DEBUG(8, ("error updating printer to tdb on disk\n"));
2104 SAFE_FREE(buf);
2106 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2107 info->sharename, info->drivername, info->portname, len));
2109 return ret;
2113 /****************************************************************************
2114 Malloc and return an NT devicemode.
2115 ****************************************************************************/
2117 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2120 char adevice[MAXDEVICENAME];
2121 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2123 if (nt_devmode == NULL) {
2124 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2125 return NULL;
2128 ZERO_STRUCTP(nt_devmode);
2130 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2131 fstrcpy(nt_devmode->devicename, adevice);
2133 fstrcpy(nt_devmode->formname, "Letter");
2135 nt_devmode->specversion = 0x0401;
2136 nt_devmode->driverversion = 0x0400;
2137 nt_devmode->size = 0x00DC;
2138 nt_devmode->driverextra = 0x0000;
2139 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2140 DEFAULTSOURCE | COPIES | SCALE |
2141 PAPERSIZE | ORIENTATION;
2142 nt_devmode->orientation = 1;
2143 nt_devmode->papersize = PAPER_LETTER;
2144 nt_devmode->paperlength = 0;
2145 nt_devmode->paperwidth = 0;
2146 nt_devmode->scale = 0x64;
2147 nt_devmode->copies = 1;
2148 nt_devmode->defaultsource = BIN_FORMSOURCE;
2149 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2150 nt_devmode->color = COLOR_MONOCHROME;
2151 nt_devmode->duplex = DUP_SIMPLEX;
2152 nt_devmode->yresolution = 0;
2153 nt_devmode->ttoption = TT_SUBDEV;
2154 nt_devmode->collate = COLLATE_FALSE;
2155 nt_devmode->icmmethod = 0;
2156 nt_devmode->icmintent = 0;
2157 nt_devmode->mediatype = 0;
2158 nt_devmode->dithertype = 0;
2160 /* non utilisés par un driver d'imprimante */
2161 nt_devmode->logpixels = 0;
2162 nt_devmode->bitsperpel = 0;
2163 nt_devmode->pelswidth = 0;
2164 nt_devmode->pelsheight = 0;
2165 nt_devmode->displayflags = 0;
2166 nt_devmode->displayfrequency = 0;
2167 nt_devmode->reserved1 = 0;
2168 nt_devmode->reserved2 = 0;
2169 nt_devmode->panningwidth = 0;
2170 nt_devmode->panningheight = 0;
2172 nt_devmode->private = NULL;
2173 return nt_devmode;
2176 /****************************************************************************
2177 Deepcopy an NT devicemode.
2178 ****************************************************************************/
2180 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2182 NT_DEVICEMODE *new_nt_devicemode = NULL;
2184 if ( !nt_devicemode )
2185 return NULL;
2187 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2188 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2189 return NULL;
2192 new_nt_devicemode->private = NULL;
2193 if (nt_devicemode->private != NULL) {
2194 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2195 SAFE_FREE(new_nt_devicemode);
2196 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2197 return NULL;
2201 return new_nt_devicemode;
2204 /****************************************************************************
2205 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2206 ****************************************************************************/
2208 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2210 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2212 if(nt_devmode == NULL)
2213 return;
2215 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2217 SAFE_FREE(nt_devmode->private);
2218 SAFE_FREE(*devmode_ptr);
2221 /****************************************************************************
2222 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2223 ****************************************************************************/
2224 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2226 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2227 NT_PRINTER_DATA *data;
2228 int i;
2230 if ( !info )
2231 return;
2233 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2235 free_nt_devicemode(&info->devmode);
2237 /* clean up all registry keys */
2239 data = &info->data;
2240 for ( i=0; i<data->num_keys; i++ ) {
2241 SAFE_FREE( data->keys[i].name );
2242 regval_ctr_destroy( &data->keys[i].values );
2244 SAFE_FREE( data->keys );
2246 /* finally the top level structure */
2248 SAFE_FREE( *info_ptr );
2252 /****************************************************************************
2253 ****************************************************************************/
2254 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2256 int len = 0;
2257 int extra_len = 0;
2258 NT_DEVICEMODE devmode;
2260 ZERO_STRUCT(devmode);
2262 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2264 if (!*nt_devmode) return len;
2266 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2267 devmode.devicename,
2268 devmode.formname,
2270 &devmode.specversion,
2271 &devmode.driverversion,
2272 &devmode.size,
2273 &devmode.driverextra,
2274 &devmode.orientation,
2275 &devmode.papersize,
2276 &devmode.paperlength,
2277 &devmode.paperwidth,
2278 &devmode.scale,
2279 &devmode.copies,
2280 &devmode.defaultsource,
2281 &devmode.printquality,
2282 &devmode.color,
2283 &devmode.duplex,
2284 &devmode.yresolution,
2285 &devmode.ttoption,
2286 &devmode.collate,
2287 &devmode.logpixels,
2289 &devmode.fields,
2290 &devmode.bitsperpel,
2291 &devmode.pelswidth,
2292 &devmode.pelsheight,
2293 &devmode.displayflags,
2294 &devmode.displayfrequency,
2295 &devmode.icmmethod,
2296 &devmode.icmintent,
2297 &devmode.mediatype,
2298 &devmode.dithertype,
2299 &devmode.reserved1,
2300 &devmode.reserved2,
2301 &devmode.panningwidth,
2302 &devmode.panningheight,
2303 &devmode.private);
2305 if (devmode.private) {
2306 /* the len in tdb_unpack is an int value and
2307 * devmode.driverextra is only a short
2309 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2310 devmode.driverextra=(uint16)extra_len;
2312 /* check to catch an invalid TDB entry so we don't segfault */
2313 if (devmode.driverextra == 0) {
2314 devmode.private = NULL;
2318 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2320 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2321 if (devmode.private)
2322 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2324 return len;
2327 /****************************************************************************
2328 Allocate and initialize a new slot.
2329 ***************************************************************************/
2331 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2333 NT_PRINTER_KEY *d;
2334 int key_index;
2336 if ( !data || !name )
2337 return -1;
2339 /* allocate another slot in the NT_PRINTER_KEY array */
2341 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2342 if ( d )
2343 data->keys = d;
2345 key_index = data->num_keys;
2347 /* initialze new key */
2349 data->num_keys++;
2350 data->keys[key_index].name = strdup( name );
2352 ZERO_STRUCTP( &data->keys[key_index].values );
2354 regval_ctr_init( &data->keys[key_index].values );
2356 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2358 return key_index;
2361 /****************************************************************************
2362 search for a registry key name in the existing printer data
2363 ***************************************************************************/
2365 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2367 int key_index = -1;
2368 int i;
2370 if ( !data || !name )
2371 return -1;
2373 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2375 /* loop over all existing keys */
2377 for ( i=0; i<data->num_keys; i++ ) {
2378 if ( strequal(data->keys[i].name, name) ) {
2379 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2380 key_index = i;
2381 break;
2386 return key_index;
2389 /****************************************************************************
2390 ***************************************************************************/
2392 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2394 int i, j;
2395 int key_len;
2396 int num_subkeys = 0;
2397 char *p;
2398 fstring *ptr, *subkeys_ptr = NULL;
2399 fstring subkeyname;
2401 if ( !data )
2402 return 0;
2404 for ( i=0; i<data->num_keys; i++ ) {
2405 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2406 /* match sure it is a subkey and not the key itself */
2408 key_len = strlen( key );
2409 if ( strlen(data->keys[i].name) == key_len )
2410 continue;
2412 /* get subkey path */
2414 p = data->keys[i].name + key_len;
2415 if ( *p == '\\' )
2416 p++;
2417 fstrcpy( subkeyname, p );
2418 if ( (p = strchr( subkeyname, '\\' )) )
2419 *p = '\0';
2421 /* don't add a key more than once */
2423 for ( j=0; j<num_subkeys; j++ ) {
2424 if ( strequal( subkeys_ptr[j], subkeyname ) )
2425 break;
2428 if ( j != num_subkeys )
2429 continue;
2431 /* found a match, so allocate space and copy the name */
2433 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2434 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2435 num_subkeys+1));
2436 SAFE_FREE( subkeys );
2437 return 0;
2440 subkeys_ptr = ptr;
2441 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2442 num_subkeys++;
2447 /* tag of the end */
2449 if (num_subkeys)
2450 fstrcpy(subkeys_ptr[num_subkeys], "" );
2452 *subkeys = subkeys_ptr;
2454 return num_subkeys;
2457 #ifdef HAVE_ADS
2458 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2459 const char *sz)
2461 smb_ucs2_t conv_str[1024];
2462 size_t str_size;
2464 regval_ctr_delvalue(ctr, val_name);
2465 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2466 STR_TERMINATE | STR_NOALIGN);
2467 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2468 (char *) conv_str, str_size);
2471 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2472 uint32 dword)
2474 regval_ctr_delvalue(ctr, val_name);
2475 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2476 (char *) &dword, sizeof(dword));
2479 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2480 BOOL b)
2482 uint8 bin_bool = (b ? 1 : 0);
2483 regval_ctr_delvalue(ctr, val_name);
2484 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2485 (char *) &bin_bool, sizeof(bin_bool));
2488 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2489 const char *multi_sz)
2491 smb_ucs2_t *conv_strs = NULL;
2492 size_t str_size;
2494 /* a multi-sz has to have a null string terminator, i.e., the last
2495 string must be followed by two nulls */
2496 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2497 conv_strs = calloc(str_size, 1);
2499 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2500 STR_TERMINATE | STR_NOALIGN);
2502 regval_ctr_delvalue(ctr, val_name);
2503 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2504 (char *) conv_strs, str_size);
2505 safe_free(conv_strs);
2509 /****************************************************************************
2510 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2512 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2513 * @return BOOL indicating success or failure
2514 ***************************************************************************/
2516 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2518 REGVAL_CTR *ctr = NULL;
2519 fstring longname;
2520 char *allocated_string = NULL;
2521 const char *ascii_str;
2522 int i;
2524 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2525 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2526 ctr = &info2->data.keys[i].values;
2528 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2529 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2531 get_myfullname(longname);
2532 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2534 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2535 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2536 SAFE_FREE(allocated_string);
2538 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2539 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2540 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2541 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2542 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2543 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2544 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2545 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2546 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2548 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2549 (info2->attributes &
2550 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2552 switch (info2->attributes & 0x3) {
2553 case 0:
2554 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2555 break;
2556 case 1:
2557 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2558 break;
2559 case 2:
2560 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2561 break;
2562 default:
2563 ascii_str = "unknown";
2565 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2567 return True;
2570 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2572 int i;
2573 REGVAL_CTR *ctr=NULL;
2575 /* find the DsSpooler key */
2576 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2577 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2578 ctr = &info2->data.keys[i].values;
2580 regval_ctr_delvalue(ctr, "objectGUID");
2581 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2582 (char *) &guid, sizeof(GUID));
2585 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2587 ADS_STATUS ads_rc;
2588 TALLOC_CTX *ctx = talloc_init("publish_it");
2589 ADS_MODLIST mods = ads_init_mods(ctx);
2590 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2591 char *srv_dn_utf8, **srv_cn_utf8;
2592 void *res = NULL;
2593 ADS_STRUCT *ads;
2594 const char *attrs[] = {"objectGUID", NULL};
2595 GUID guid;
2596 WERROR win_rc = WERR_OK;
2598 ZERO_STRUCT(guid);
2599 /* set the DsSpooler info and attributes */
2600 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2601 return WERR_NOMEM;
2602 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2603 win_rc = mod_a_printer(*printer, 2);
2604 if (!W_ERROR_IS_OK(win_rc)) {
2605 DEBUG(3, ("err %d saving data\n",
2606 W_ERROR_V(win_rc)));
2607 return win_rc;
2610 /* Build the ads mods */
2611 get_local_printer_publishing_data(ctx, &mods,
2612 &printer->info_2->data);
2613 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2614 printer->info_2->sharename);
2616 /* initial ads structure */
2618 ads = ads_init(NULL, NULL, NULL);
2619 if (!ads) {
2620 DEBUG(3, ("ads_init() failed\n"));
2621 return WERR_SERVER_UNAVAILABLE;
2623 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2624 SAFE_FREE(ads->auth.password);
2625 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2626 NULL, NULL);
2628 /* ads_connect() will find the DC for us */
2629 ads_rc = ads_connect(ads);
2630 if (!ADS_ERR_OK(ads_rc)) {
2631 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2632 ads_destroy(&ads);
2633 return WERR_ACCESS_DENIED;
2636 /* figure out where to publish */
2637 ads_find_machine_acct(ads, &res, global_myname());
2639 /* We use ldap_get_dn here as we need the answer
2640 * in utf8 to call ldap_explode_dn(). JRA. */
2642 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2643 if (!srv_dn_utf8) {
2644 ads_destroy(&ads);
2645 return WERR_SERVER_UNAVAILABLE;
2647 ads_msgfree(ads, res);
2648 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2649 if (!srv_cn_utf8) {
2650 ldap_memfree(srv_dn_utf8);
2651 ads_destroy(&ads);
2652 return WERR_SERVER_UNAVAILABLE;
2654 /* Now convert to CH_UNIX. */
2655 if (pull_utf8_allocate((void **) &srv_dn, srv_dn_utf8) == (size_t)-1) {
2656 ldap_memfree(srv_dn_utf8);
2657 ldap_memfree(srv_cn_utf8);
2658 ads_destroy(&ads);
2659 return WERR_SERVER_UNAVAILABLE;
2661 if (pull_utf8_allocate((void **) &srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2662 ldap_memfree(srv_dn_utf8);
2663 ldap_memfree(srv_cn_utf8);
2664 ads_destroy(&ads);
2665 SAFE_FREE(srv_dn);
2666 return WERR_SERVER_UNAVAILABLE;
2669 ldap_memfree(srv_dn_utf8);
2670 ldap_memfree(srv_cn_utf8);
2672 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2673 printer->info_2->sharename, srv_dn);
2675 SAFE_FREE(srv_dn);
2676 SAFE_FREE(srv_cn_0);
2678 /* publish it */
2679 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2680 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2681 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2683 /* retreive the guid and store it locally */
2684 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2685 ads_memfree(ads, prt_dn);
2686 ads_pull_guid(ads, res, &guid);
2687 ads_msgfree(ads, res);
2688 store_printer_guid(printer->info_2, guid);
2689 win_rc = mod_a_printer(*printer, 2);
2692 safe_free(prt_dn);
2693 ads_destroy(&ads);
2695 return WERR_OK;
2698 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2700 ADS_STATUS ads_rc;
2701 ADS_STRUCT *ads;
2702 void *res;
2703 char *prt_dn = NULL;
2704 WERROR win_rc;
2706 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2707 win_rc = mod_a_printer(*printer, 2);
2708 if (!W_ERROR_IS_OK(win_rc)) {
2709 DEBUG(3, ("err %d saving data\n",
2710 W_ERROR_V(win_rc)));
2711 return win_rc;
2714 ads = ads_init(NULL, NULL, NULL);
2715 if (!ads) {
2716 DEBUG(3, ("ads_init() failed\n"));
2717 return WERR_SERVER_UNAVAILABLE;
2719 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2720 SAFE_FREE(ads->auth.password);
2721 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2722 NULL, NULL);
2724 /* ads_connect() will find the DC for us */
2725 ads_rc = ads_connect(ads);
2726 if (!ADS_ERR_OK(ads_rc)) {
2727 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2728 ads_destroy(&ads);
2729 return WERR_ACCESS_DENIED;
2732 /* remove the printer from the directory */
2733 ads_rc = ads_find_printer_on_server(ads, &res,
2734 printer->info_2->sharename, global_myname());
2735 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2736 prt_dn = ads_get_dn(ads, res);
2737 ads_msgfree(ads, res);
2738 ads_rc = ads_del_dn(ads, prt_dn);
2739 ads_memfree(ads, prt_dn);
2742 ads_destroy(&ads);
2743 return WERR_OK;
2746 /****************************************************************************
2747 * Publish a printer in the directory
2749 * @param snum describing printer service
2750 * @return WERROR indicating status of publishing
2751 ***************************************************************************/
2753 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2755 NT_PRINTER_INFO_LEVEL *printer = NULL;
2756 WERROR win_rc;
2758 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2759 if (!W_ERROR_IS_OK(win_rc))
2760 return win_rc;
2762 switch(action) {
2763 case SPOOL_DS_PUBLISH:
2764 case SPOOL_DS_UPDATE:
2765 win_rc = publish_it(printer);
2766 break;
2767 case SPOOL_DS_UNPUBLISH:
2768 win_rc = unpublish_it(printer);
2769 break;
2770 default:
2771 win_rc = WERR_NOT_SUPPORTED;
2775 free_a_printer(&printer, 2);
2776 return win_rc;
2779 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2781 NT_PRINTER_INFO_LEVEL *printer = NULL;
2782 REGVAL_CTR *ctr;
2783 REGISTRY_VALUE *guid_val;
2784 WERROR win_rc;
2785 int i;
2788 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2789 if (!W_ERROR_IS_OK(win_rc))
2790 return False;
2792 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2793 return False;
2795 if ((i = lookup_printerkey(&printer->info_2->data,
2796 SPOOL_DSSPOOLER_KEY)) < 0)
2797 return False;
2799 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2800 return False;
2803 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2804 return False;
2807 if (regval_size(guid_val) == sizeof(GUID))
2808 memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2810 return True;
2813 #else
2814 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2816 return WERR_OK;
2818 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2820 return False;
2822 #endif
2823 /****************************************************************************
2824 ***************************************************************************/
2826 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2828 NT_PRINTER_DATA *data;
2829 int i;
2830 int removed_keys = 0;
2831 int empty_slot;
2833 data = &p2->data;
2834 empty_slot = data->num_keys;
2836 if ( !key )
2837 return WERR_INVALID_PARAM;
2839 /* remove all keys */
2841 if ( !strlen(key) ) {
2842 for ( i=0; i<data->num_keys; i++ ) {
2843 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2844 data->keys[i].name));
2846 SAFE_FREE( data->keys[i].name );
2847 regval_ctr_destroy( &data->keys[i].values );
2850 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2851 p2->printername ));
2853 SAFE_FREE( data->keys );
2854 ZERO_STRUCTP( data );
2856 return WERR_OK;
2859 /* remove a specific key (and all subkeys) */
2861 for ( i=0; i<data->num_keys; i++ ) {
2862 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2863 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2864 data->keys[i].name));
2866 SAFE_FREE( data->keys[i].name );
2867 regval_ctr_destroy( &data->keys[i].values );
2869 /* mark the slot as empty */
2871 ZERO_STRUCTP( &data->keys[i] );
2875 /* find the first empty slot */
2877 for ( i=0; i<data->num_keys; i++ ) {
2878 if ( !data->keys[i].name ) {
2879 empty_slot = i;
2880 removed_keys++;
2881 break;
2885 if ( i == data->num_keys )
2886 /* nothing was removed */
2887 return WERR_INVALID_PARAM;
2889 /* move everything down */
2891 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2892 if ( data->keys[i].name ) {
2893 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2894 ZERO_STRUCTP( &data->keys[i] );
2895 empty_slot++;
2896 removed_keys++;
2900 /* update count */
2902 data->num_keys -= removed_keys;
2904 /* sanity check to see if anything is left */
2906 if ( !data->num_keys ) {
2907 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2909 SAFE_FREE( data->keys );
2910 ZERO_STRUCTP( data );
2913 return WERR_OK;
2916 /****************************************************************************
2917 ***************************************************************************/
2919 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2921 WERROR result = WERR_OK;
2922 int key_index;
2924 /* we must have names on non-zero length */
2926 if ( !key || !*key|| !value || !*value )
2927 return WERR_INVALID_NAME;
2929 /* find the printer key first */
2931 key_index = lookup_printerkey( &p2->data, key );
2932 if ( key_index == -1 )
2933 return WERR_OK;
2935 /* make sure the value exists so we can return the correct error code */
2937 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2938 return WERR_BADFILE;
2940 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2942 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2943 key, value ));
2945 return result;
2948 /****************************************************************************
2949 ***************************************************************************/
2951 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2952 uint32 type, uint8 *data, int real_len )
2954 WERROR result = WERR_OK;
2955 int key_index;
2957 /* we must have names on non-zero length */
2959 if ( !key || !*key|| !value || !*value )
2960 return WERR_INVALID_NAME;
2962 /* find the printer key first */
2964 key_index = lookup_printerkey( &p2->data, key );
2965 if ( key_index == -1 )
2966 key_index = add_new_printer_key( &p2->data, key );
2968 if ( key_index == -1 )
2969 return WERR_NOMEM;
2971 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2972 type, (const char *)data, real_len );
2974 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2975 key, value, type, real_len ));
2977 return result;
2980 /****************************************************************************
2981 ***************************************************************************/
2983 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2985 int key_index;
2987 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2988 return NULL;
2990 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2991 key, value ));
2993 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2996 /****************************************************************************
2997 Unpack a list of registry values frem the TDB
2998 ***************************************************************************/
3000 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3002 int len = 0;
3003 uint32 type;
3004 pstring string, valuename, keyname;
3005 char *str;
3006 int size;
3007 uint8 *data_p;
3008 REGISTRY_VALUE *regval_p;
3009 int key_index;
3011 /* add the "PrinterDriverData" key first for performance reasons */
3013 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3015 /* loop and unpack the rest of the registry values */
3017 while ( True ) {
3019 /* check to see if there are any more registry values */
3021 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3022 if ( !regval_p )
3023 break;
3025 /* unpack the next regval */
3027 len += tdb_unpack(buf+len, buflen-len, "fdB",
3028 string,
3029 &type,
3030 &size,
3031 &data_p);
3034 * break of the keyname from the value name.
3035 * Should only be one '\' in the string returned.
3038 str = strrchr( string, '\\');
3040 /* Put in "PrinterDriverData" is no key specified */
3042 if ( !str ) {
3043 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3044 pstrcpy( valuename, string );
3046 else {
3047 *str = '\0';
3048 pstrcpy( keyname, string );
3049 pstrcpy( valuename, str+1 );
3052 /* see if we need a new key */
3054 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3055 key_index = add_new_printer_key( printer_data, keyname );
3057 if ( key_index == -1 ) {
3058 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3059 keyname));
3060 break;
3063 /* add the new value */
3065 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3067 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3069 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3072 return len;
3075 /****************************************************************************
3076 ***************************************************************************/
3078 static void map_to_os2_driver(fstring drivername)
3080 static BOOL initialised=False;
3081 static fstring last_from,last_to;
3082 char *mapfile = lp_os2_driver_map();
3083 char **lines = NULL;
3084 int numlines = 0;
3085 int i;
3087 if (!strlen(drivername))
3088 return;
3090 if (!*mapfile)
3091 return;
3093 if (!initialised) {
3094 *last_from = *last_to = 0;
3095 initialised = True;
3098 if (strequal(drivername,last_from)) {
3099 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3100 fstrcpy(drivername,last_to);
3101 return;
3104 lines = file_lines_load(mapfile, &numlines);
3105 if (numlines == 0) {
3106 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3107 return;
3110 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3112 for( i = 0; i < numlines; i++) {
3113 char *nt_name = lines[i];
3114 char *os2_name = strchr(nt_name,'=');
3116 if (!os2_name)
3117 continue;
3119 *os2_name++ = 0;
3121 while (isspace(*nt_name))
3122 nt_name++;
3124 if (!*nt_name || strchr("#;",*nt_name))
3125 continue;
3128 int l = strlen(nt_name);
3129 while (l && isspace(nt_name[l-1])) {
3130 nt_name[l-1] = 0;
3131 l--;
3135 while (isspace(*os2_name))
3136 os2_name++;
3139 int l = strlen(os2_name);
3140 while (l && isspace(os2_name[l-1])) {
3141 os2_name[l-1] = 0;
3142 l--;
3146 if (strequal(nt_name,drivername)) {
3147 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3148 fstrcpy(last_from,drivername);
3149 fstrcpy(last_to,os2_name);
3150 fstrcpy(drivername,os2_name);
3151 file_lines_free(lines);
3152 return;
3156 file_lines_free(lines);
3159 /****************************************************************************
3160 Get a default printer info 2 struct.
3161 ****************************************************************************/
3162 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3164 int snum;
3165 NT_PRINTER_INFO_LEVEL_2 info;
3167 ZERO_STRUCT(info);
3169 snum = lp_servicenumber(sharename);
3171 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3172 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3173 get_called_name(), sharename);
3174 fstrcpy(info.sharename, sharename);
3175 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3177 /* by setting the driver name to an empty string, a local NT admin
3178 can now run the **local** APW to install a local printer driver
3179 for a Samba shared printer in 2.2. Without this, drivers **must** be
3180 installed on the Samba server for NT clients --jerry */
3181 #if 0 /* JERRY --do not uncomment-- */
3182 if (!*info.drivername)
3183 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3184 #endif
3187 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3189 pstrcpy(info.comment, "");
3190 fstrcpy(info.printprocessor, "winprint");
3191 fstrcpy(info.datatype, "RAW");
3193 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3195 info.starttime = 0; /* Minutes since 12:00am GMT */
3196 info.untiltime = 0; /* Minutes since 12:00am GMT */
3197 info.priority = 1;
3198 info.default_priority = 1;
3199 info.setuptime = (uint32)time(NULL);
3202 * I changed this as I think it is better to have a generic
3203 * DEVMODE than to crash Win2k explorer.exe --jerry
3204 * See the HP Deskjet 990c Win2k drivers for an example.
3206 * However the default devmode appears to cause problems
3207 * with the HP CLJ 8500 PCL driver. Hence the addition of
3208 * the "default devmode" parameter --jerry 22/01/2002
3211 if (lp_default_devmode(snum)) {
3212 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3213 goto fail;
3215 else {
3216 info.devmode = NULL;
3219 /* This will get the current RPC talloc context, but we should be
3220 passing this as a parameter... fixme... JRA ! */
3222 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3223 goto fail;
3225 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3226 if (! *info_ptr) {
3227 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3228 goto fail;
3231 return WERR_OK;
3233 fail:
3234 if (info.devmode)
3235 free_nt_devicemode(&info.devmode);
3236 return WERR_ACCESS_DENIED;
3239 /****************************************************************************
3240 ****************************************************************************/
3241 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3243 pstring key;
3244 NT_PRINTER_INFO_LEVEL_2 info;
3245 int len = 0;
3246 TDB_DATA kbuf, dbuf;
3247 fstring printername;
3248 char adevice[MAXDEVICENAME];
3250 ZERO_STRUCT(info);
3252 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3254 kbuf.dptr = key;
3255 kbuf.dsize = strlen(key)+1;
3257 dbuf = tdb_fetch(tdb_printers, kbuf);
3258 if (!dbuf.dptr)
3259 return get_a_printer_2_default(info_ptr, sharename);
3261 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3262 &info.attributes,
3263 &info.priority,
3264 &info.default_priority,
3265 &info.starttime,
3266 &info.untiltime,
3267 &info.status,
3268 &info.cjobs,
3269 &info.averageppm,
3270 &info.changeid,
3271 &info.c_setprinter,
3272 &info.setuptime,
3273 info.servername,
3274 info.printername,
3275 info.sharename,
3276 info.portname,
3277 info.drivername,
3278 info.comment,
3279 info.location,
3280 info.sepfile,
3281 info.printprocessor,
3282 info.datatype,
3283 info.parameters);
3285 /* Samba has to have shared raw drivers. */
3286 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3288 /* Restore the stripped strings. */
3289 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3290 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3291 info.printername);
3292 fstrcpy(info.printername, printername);
3294 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3297 * Some client drivers freak out if there is a NULL devmode
3298 * (probably the driver is not checking before accessing
3299 * the devmode pointer) --jerry
3301 * See comments in get_a_printer_2_default()
3304 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3305 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3306 printername));
3307 info.devmode = construct_nt_devicemode(printername);
3310 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3311 if (info.devmode) {
3312 fstrcpy(info.devmode->devicename, adevice);
3315 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3317 /* This will get the current RPC talloc context, but we should be
3318 passing this as a parameter... fixme... JRA ! */
3320 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3322 /* Fix for OS/2 drivers. */
3324 if (get_remote_arch() == RA_OS2)
3325 map_to_os2_driver(info.drivername);
3327 SAFE_FREE(dbuf.dptr);
3328 *info_ptr=memdup(&info, sizeof(info));
3330 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3331 sharename, info.printername, info.drivername));
3333 return WERR_OK;
3336 /****************************************************************************
3337 Debugging function, dump at level 6 the struct in the logs.
3338 ****************************************************************************/
3339 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3341 uint32 result;
3342 NT_PRINTER_INFO_LEVEL_2 *info2;
3344 DEBUG(106,("Dumping printer at level [%d]\n", level));
3346 switch (level) {
3347 case 2:
3349 if (printer.info_2 == NULL)
3350 result=5;
3351 else
3353 info2=printer.info_2;
3355 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3356 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3357 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3358 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3359 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3360 DEBUGADD(106,("status:[%d]\n", info2->status));
3361 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3362 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3363 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3364 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3365 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3367 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3368 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3369 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3370 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3371 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3372 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3373 DEBUGADD(106,("location:[%s]\n", info2->location));
3374 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3375 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3376 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3377 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3378 result=0;
3380 break;
3382 default:
3383 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3384 result=1;
3385 break;
3388 return result;
3391 /****************************************************************************
3392 Update the changeid time.
3393 This is SO NASTY as some drivers need this to change, others need it
3394 static. This value will change every second, and I must hope that this
3395 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3396 UTAH ! JRA.
3397 ****************************************************************************/
3399 static uint32 rev_changeid(void)
3401 struct timeval tv;
3403 get_process_uptime(&tv);
3405 #if 1 /* JERRY */
3406 /* Return changeid as msec since spooler restart */
3407 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3408 #else
3410 * This setting seems to work well but is too untested
3411 * to replace the above calculation. Left in for experiementation
3412 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3414 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3415 #endif
3419 * The function below are the high level ones.
3420 * only those ones must be called from the spoolss code.
3421 * JFM.
3424 /****************************************************************************
3425 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3426 ****************************************************************************/
3428 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3430 WERROR result;
3432 dump_a_printer(printer, level);
3435 * invalidate cache for all open handles to this printer.
3436 * cache for a given handle will be updated on the next
3437 * get_a_printer()
3440 invalidate_printer_hnd_cache( printer.info_2->sharename );
3442 switch (level) {
3443 case 2:
3446 * Update the changestamp. Emperical tests show that the
3447 * ChangeID is always updated,but c_setprinter is
3448 * global spooler variable (not per printer).
3451 /* ChangeID **must** be increasing over the lifetime
3452 of client's spoolss service in order for the
3453 client's cache to show updates */
3455 printer.info_2->changeid = rev_changeid();
3458 * Because one day someone will ask:
3459 * NT->NT An admin connection to a remote
3460 * printer show changes imeediately in
3461 * the properities dialog
3463 * A non-admin connection will only show the
3464 * changes after viewing the properites page
3465 * 2 times. Seems to be related to a
3466 * race condition in the client between the spooler
3467 * updating the local cache and the Explorer.exe GUI
3468 * actually displaying the properties.
3470 * This is fixed in Win2k. admin/non-admin
3471 * connections both display changes immediately.
3473 * 14/12/01 --jerry
3476 result=update_a_printer_2(printer.info_2);
3478 break;
3480 default:
3481 result=WERR_UNKNOWN_LEVEL;
3482 break;
3485 return result;
3488 /****************************************************************************
3489 Initialize printer devmode & data with previously saved driver init values.
3490 ****************************************************************************/
3492 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3494 int len = 0;
3495 pstring key;
3496 TDB_DATA kbuf, dbuf;
3497 NT_PRINTER_INFO_LEVEL_2 info;
3500 ZERO_STRUCT(info);
3503 * Delete any printer data 'values' already set. When called for driver
3504 * replace, there will generally be some, but during an add printer, there
3505 * should not be any (if there are delete them).
3508 delete_all_printer_data( info_ptr, "" );
3510 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3512 kbuf.dptr = key;
3513 kbuf.dsize = strlen(key)+1;
3515 dbuf = tdb_fetch(tdb_drivers, kbuf);
3516 if (!dbuf.dptr) {
3518 * When changing to a driver that has no init info in the tdb, remove
3519 * the previous drivers init info and leave the new on blank.
3521 free_nt_devicemode(&info_ptr->devmode);
3522 return False;
3526 * Get the saved DEVMODE..
3529 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3532 * The saved DEVMODE contains the devicename from the printer used during
3533 * the initialization save. Change it to reflect the new printer.
3536 if ( info.devmode ) {
3537 ZERO_STRUCT(info.devmode->devicename);
3538 fstrcpy(info.devmode->devicename, info_ptr->printername);
3542 * NT/2k does not change out the entire DeviceMode of a printer
3543 * when changing the driver. Only the driverextra, private, &
3544 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3546 * Later examination revealed that Windows NT/2k does reset the
3547 * the printer's device mode, bit **only** when you change a
3548 * property of the device mode such as the page orientation.
3549 * --jerry
3553 /* Bind the saved DEVMODE to the new the printer */
3555 free_nt_devicemode(&info_ptr->devmode);
3556 info_ptr->devmode = info.devmode;
3558 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3559 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3561 /* Add the printer data 'values' to the new printer */
3563 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3566 SAFE_FREE(dbuf.dptr);
3568 return True;
3571 /****************************************************************************
3572 Initialize printer devmode & data with previously saved driver init values.
3573 When a printer is created using AddPrinter, the drivername bound to the
3574 printer is used to lookup previously saved driver initialization info, which
3575 is bound to the new printer.
3576 ****************************************************************************/
3578 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3580 BOOL result = False;
3582 switch (level) {
3583 case 2:
3584 result = set_driver_init_2(printer->info_2);
3585 break;
3587 default:
3588 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3589 level));
3590 break;
3593 return result;
3596 /****************************************************************************
3597 Delete driver init data stored for a specified driver
3598 ****************************************************************************/
3600 BOOL del_driver_init(char *drivername)
3602 pstring key;
3603 TDB_DATA kbuf;
3605 if (!drivername || !*drivername) {
3606 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3607 return False;
3610 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3612 kbuf.dptr = key;
3613 kbuf.dsize = strlen(key)+1;
3615 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3617 return (tdb_delete(tdb_drivers, kbuf) == 0);
3620 /****************************************************************************
3621 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3622 in the tdb. Note: this is different from the driver entry and the printer
3623 entry. There should be a single driver init entry for each driver regardless
3624 of whether it was installed from NT or 2K. Technically, they should be
3625 different, but they work out to the same struct.
3626 ****************************************************************************/
3628 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3630 pstring key;
3631 char *buf;
3632 int buflen, len, ret;
3633 TDB_DATA kbuf, dbuf;
3635 buf = NULL;
3636 buflen = 0;
3638 again:
3639 len = 0;
3640 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3642 len += pack_values( &info->data, buf+len, buflen-len );
3644 if (buflen != len) {
3645 char *tb;
3647 tb = (char *)Realloc(buf, len);
3648 if (!tb) {
3649 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3650 ret = -1;
3651 goto done;
3653 else
3654 buf = tb;
3655 buflen = len;
3656 goto again;
3659 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3661 kbuf.dptr = key;
3662 kbuf.dsize = strlen(key)+1;
3663 dbuf.dptr = buf;
3664 dbuf.dsize = len;
3666 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3668 done:
3669 if (ret == -1)
3670 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3672 SAFE_FREE(buf);
3674 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3675 info->sharename, info->drivername));
3677 return ret;
3680 /****************************************************************************
3681 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3682 ****************************************************************************/
3684 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3686 uint32 result;
3688 dump_a_printer(printer, level);
3690 switch (level) {
3691 case 2:
3692 result = update_driver_init_2(printer.info_2);
3693 break;
3694 default:
3695 result = 1;
3696 break;
3699 return result;
3702 /****************************************************************************
3703 Convert the printer data value, a REG_BINARY array, into an initialization
3704 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3705 got to keep the endians happy :).
3706 ****************************************************************************/
3708 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3710 BOOL result = False;
3711 prs_struct ps;
3712 DEVICEMODE devmode;
3714 ZERO_STRUCT(devmode);
3716 prs_init(&ps, 0, ctx, UNMARSHALL);
3717 ps.data_p = (char *)data;
3718 ps.buffer_size = data_len;
3720 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3721 result = convert_devicemode("", &devmode, &nt_devmode);
3722 else
3723 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3725 return result;
3728 /****************************************************************************
3729 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3731 1. Use the driver's config DLL to this UNC printername and:
3732 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3733 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3734 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3736 The last step triggers saving the "driver initialization" information for
3737 this printer into the tdb. Later, new printers that use this driver will
3738 have this initialization information bound to them. This simulates the
3739 driver initialization, as if it had run on the Samba server (as it would
3740 have done on NT).
3742 The Win32 client side code requirement sucks! But until we can run arbitrary
3743 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3745 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3746 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3747 about it and you will realize why. JRR 010720
3748 ****************************************************************************/
3750 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3752 WERROR status = WERR_OK;
3753 TALLOC_CTX *ctx = NULL;
3754 NT_DEVICEMODE *nt_devmode = NULL;
3755 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3758 * When the DEVMODE is already set on the printer, don't try to unpack it.
3760 DEBUG(8,("save_driver_init_2: Enter...\n"));
3762 if ( !printer->info_2->devmode && data_len ) {
3764 * Set devmode on printer info, so entire printer initialization can be
3765 * saved to tdb.
3768 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3769 return WERR_NOMEM;
3771 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3772 status = WERR_NOMEM;
3773 goto done;
3776 ZERO_STRUCTP(nt_devmode);
3779 * The DEVMODE is held in the 'data' component of the param in raw binary.
3780 * Convert it to to a devmode structure
3782 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3783 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3784 status = WERR_INVALID_PARAM;
3785 goto done;
3788 printer->info_2->devmode = nt_devmode;
3792 * Pack up and add (or update) the DEVMODE and any current printer data to
3793 * a 'driver init' element in the tdb
3797 if ( update_driver_init(*printer, 2) != 0 ) {
3798 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3799 status = WERR_NOMEM;
3800 goto done;
3804 * If driver initialization info was successfully saved, set the current
3805 * printer to match it. This allows initialization of the current printer
3806 * as well as the driver.
3808 status = mod_a_printer(*printer, 2);
3809 if (!W_ERROR_IS_OK(status)) {
3810 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3811 printer->info_2->printername));
3814 done:
3815 talloc_destroy(ctx);
3816 free_nt_devicemode( &nt_devmode );
3818 printer->info_2->devmode = tmp_devmode;
3820 return status;
3823 /****************************************************************************
3824 Update the driver init info (DEVMODE and specifics) for a printer
3825 ****************************************************************************/
3827 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3829 WERROR status = WERR_OK;
3831 switch (level) {
3832 case 2:
3833 status = save_driver_init_2( printer, data, data_len );
3834 break;
3835 default:
3836 status = WERR_UNKNOWN_LEVEL;
3837 break;
3840 return status;
3843 /****************************************************************************
3844 Deep copy a NT_PRINTER_DATA
3845 ****************************************************************************/
3847 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3849 int i, j, num_vals, new_key_index;
3850 REGVAL_CTR *src_key, *dst_key;
3852 if ( !dst || !src )
3853 return NT_STATUS_NO_MEMORY;
3855 for ( i=0; i<src->num_keys; i++ ) {
3857 /* create a new instance of the printerkey in the destination
3858 printer_data object */
3860 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3861 dst_key = &dst->keys[new_key_index].values;
3863 src_key = &src->keys[i].values;
3864 num_vals = regval_ctr_numvals( src_key );
3866 /* dup the printer entire printer key */
3868 for ( j=0; j<num_vals; j++ ) {
3869 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3873 return NT_STATUS_OK;
3876 /****************************************************************************
3877 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3878 Caller must free.
3879 ****************************************************************************/
3881 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3883 NT_PRINTER_INFO_LEVEL_2 *copy;
3885 if ( !printer )
3886 return NULL;
3888 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3889 return NULL;
3891 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3893 /* malloc()'d members copied here */
3895 copy->devmode = dup_nt_devicemode( printer->devmode );
3897 ZERO_STRUCT( copy->data );
3898 copy_printer_data( &copy->data, &printer->data );
3900 /* this is talloc()'d; very ugly that we have a structure that
3901 is half malloc()'d and half talloc()'d but that is the way
3902 that the PRINTER_INFO stuff is written right now. --jerry */
3904 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3906 return copy;
3909 /****************************************************************************
3910 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3911 ****************************************************************************/
3913 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3914 const char *sharename)
3916 WERROR result;
3917 NT_PRINTER_INFO_LEVEL *printer = NULL;
3919 *pp_printer = NULL;
3921 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3923 switch (level) {
3924 case 2:
3925 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3926 DEBUG(0,("get_a_printer: malloc fail.\n"));
3927 return WERR_NOMEM;
3929 ZERO_STRUCTP(printer);
3932 * check for cache first. A Printer handle cannot changed
3933 * to another printer object so we only check that the printer
3934 * is actually for a printer and that the printer_info pointer
3935 * is valid
3937 if ( print_hnd
3938 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3939 && print_hnd->printer_info )
3941 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3942 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3944 SAFE_FREE(printer);
3945 return WERR_NOMEM;
3948 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3950 *pp_printer = printer;
3951 result = WERR_OK;
3953 break;
3956 /* no cache for this handle; see if we can match one from another handle */
3958 if ( print_hnd )
3959 result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename);
3961 /* fail to disk if we don't have it with any open handle */
3963 if ( !print_hnd || !W_ERROR_IS_OK(result) )
3964 result = get_a_printer_2(&printer->info_2, sharename);
3966 /* we have a new printer now. Save it with this handle */
3968 if ( W_ERROR_IS_OK(result) ) {
3969 dump_a_printer(*printer, level);
3971 /* save a copy in cache */
3972 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3973 if ( !print_hnd->printer_info )
3974 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3976 if ( print_hnd->printer_info ) {
3977 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3979 /* don't fail the lookup just because the cache update failed */
3980 if ( !print_hnd->printer_info->info_2 )
3981 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3984 *pp_printer = printer;
3986 else
3987 SAFE_FREE(printer);
3989 break;
3991 default:
3992 result=WERR_UNKNOWN_LEVEL;
3993 break;
3996 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3998 return result;
4001 /****************************************************************************
4002 Deletes a NT_PRINTER_INFO_LEVEL struct.
4003 ****************************************************************************/
4005 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4007 uint32 result;
4008 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4010 DEBUG(104,("freeing a printer at level [%d]\n", level));
4012 if (printer == NULL)
4013 return 0;
4015 switch (level) {
4016 case 2:
4017 if (printer->info_2 != NULL) {
4018 free_nt_printer_info_level_2(&printer->info_2);
4019 result=0;
4020 } else
4021 result=4;
4022 break;
4024 default:
4025 result=1;
4026 break;
4029 SAFE_FREE(*pp_printer);
4030 return result;
4033 /****************************************************************************
4034 ****************************************************************************/
4035 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4037 uint32 result;
4038 DEBUG(104,("adding a printer at level [%d]\n", level));
4039 dump_a_printer_driver(driver, level);
4041 switch (level) {
4042 case 3:
4043 result=add_a_printer_driver_3(driver.info_3);
4044 break;
4046 case 6:
4047 result=add_a_printer_driver_6(driver.info_6);
4048 break;
4050 default:
4051 result=1;
4052 break;
4055 return result;
4057 /****************************************************************************
4058 ****************************************************************************/
4060 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4061 fstring drivername, const char *architecture, uint32 version)
4063 WERROR result;
4065 switch (level) {
4066 case 3:
4067 /* Sometime we just want any version of the driver */
4069 if ( version == DRIVER_ANY_VERSION ) {
4070 /* look for Win2k first and then for NT4 */
4071 result = get_a_printer_driver_3(&driver->info_3, drivername,
4072 architecture, 3);
4074 if ( !W_ERROR_IS_OK(result) ) {
4075 result = get_a_printer_driver_3( &driver->info_3,
4076 drivername, architecture, 2 );
4078 } else {
4079 result = get_a_printer_driver_3(&driver->info_3, drivername,
4080 architecture, version);
4082 break;
4084 default:
4085 result=W_ERROR(1);
4086 break;
4089 if (W_ERROR_IS_OK(result))
4090 dump_a_printer_driver(*driver, level);
4092 return result;
4095 /****************************************************************************
4096 ****************************************************************************/
4097 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4099 uint32 result;
4101 switch (level) {
4102 case 3:
4104 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4105 if (driver.info_3 != NULL)
4107 info3=driver.info_3;
4108 SAFE_FREE(info3->dependentfiles);
4109 ZERO_STRUCTP(info3);
4110 SAFE_FREE(info3);
4111 result=0;
4112 } else {
4113 result=4;
4115 break;
4117 case 6:
4119 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4120 if (driver.info_6 != NULL) {
4121 info6=driver.info_6;
4122 SAFE_FREE(info6->dependentfiles);
4123 SAFE_FREE(info6->previousnames);
4124 ZERO_STRUCTP(info6);
4125 SAFE_FREE(info6);
4126 result=0;
4127 } else {
4128 result=4;
4130 break;
4132 default:
4133 result=1;
4134 break;
4136 return result;
4140 /****************************************************************************
4141 Determine whether or not a particular driver is currently assigned
4142 to a printer
4143 ****************************************************************************/
4145 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4147 int snum;
4148 int n_services = lp_numservices();
4149 NT_PRINTER_INFO_LEVEL *printer = NULL;
4151 if ( !info_3 )
4152 return False;
4154 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4156 /* loop through the printers.tdb and check for the drivername */
4158 for (snum=0; snum<n_services; snum++) {
4159 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4160 continue;
4162 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4163 continue;
4165 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4166 free_a_printer( &printer, 2 );
4167 return True;
4170 free_a_printer( &printer, 2 );
4173 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4175 /* report that the driver is not in use by default */
4177 return False;
4181 /**********************************************************************
4182 Check to see if a ogiven file is in use by *info
4183 *********************************************************************/
4185 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4187 int i = 0;
4189 if ( !info )
4190 return False;
4192 if ( strequal(file, info->driverpath) )
4193 return True;
4195 if ( strequal(file, info->datafile) )
4196 return True;
4198 if ( strequal(file, info->configfile) )
4199 return True;
4201 if ( strequal(file, info->helpfile) )
4202 return True;
4204 /* see of there are any dependent files to examine */
4206 if ( !info->dependentfiles )
4207 return False;
4209 while ( *info->dependentfiles[i] ) {
4210 if ( strequal(file, info->dependentfiles[i]) )
4211 return True;
4212 i++;
4215 return False;
4219 /**********************************************************************
4220 Utility function to remove the dependent file pointed to by the
4221 input parameter from the list
4222 *********************************************************************/
4224 static void trim_dependent_file( fstring files[], int idx )
4227 /* bump everything down a slot */
4229 while( *files[idx+1] ) {
4230 fstrcpy( files[idx], files[idx+1] );
4231 idx++;
4234 *files[idx] = '\0';
4236 return;
4239 /**********************************************************************
4240 Check if any of the files used by src are also used by drv
4241 *********************************************************************/
4243 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4244 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4246 BOOL in_use = False;
4247 int i = 0;
4249 if ( !src || !drv )
4250 return False;
4252 /* check each file. Remove it from the src structure if it overlaps */
4254 if ( drv_file_in_use(src->driverpath, drv) ) {
4255 in_use = True;
4256 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4257 fstrcpy( src->driverpath, "" );
4260 if ( drv_file_in_use(src->datafile, drv) ) {
4261 in_use = True;
4262 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4263 fstrcpy( src->datafile, "" );
4266 if ( drv_file_in_use(src->configfile, drv) ) {
4267 in_use = True;
4268 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4269 fstrcpy( src->configfile, "" );
4272 if ( drv_file_in_use(src->helpfile, drv) ) {
4273 in_use = True;
4274 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4275 fstrcpy( src->helpfile, "" );
4278 /* are there any dependentfiles to examine? */
4280 if ( !src->dependentfiles )
4281 return in_use;
4283 while ( *src->dependentfiles[i] ) {
4284 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4285 in_use = True;
4286 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4287 trim_dependent_file( src->dependentfiles, i );
4288 } else
4289 i++;
4292 return in_use;
4295 /****************************************************************************
4296 Determine whether or not a particular driver files are currently being
4297 used by any other driver.
4299 Return value is True if any files were in use by other drivers
4300 and False otherwise.
4302 Upon return, *info has been modified to only contain the driver files
4303 which are not in use
4304 ****************************************************************************/
4306 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4308 int i;
4309 int ndrivers;
4310 uint32 version;
4311 fstring *list = NULL;
4312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4314 if ( !info )
4315 return False;
4317 version = info->cversion;
4319 /* loop over all driver versions */
4321 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4323 /* get the list of drivers */
4325 list = NULL;
4326 ndrivers = get_ntdrivers(&list, info->environment, version);
4328 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4329 ndrivers, info->environment, version));
4331 /* check each driver for overlap in files */
4333 for (i=0; i<ndrivers; i++) {
4334 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4336 ZERO_STRUCT(driver);
4338 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4339 SAFE_FREE(list);
4340 return True;
4343 /* check if d2 uses any files from d1 */
4344 /* only if this is a different driver than the one being deleted */
4346 if ( !strequal(info->name, driver.info_3->name) ) {
4347 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4348 free_a_printer_driver(driver, 3);
4349 SAFE_FREE( list );
4350 return True;
4354 free_a_printer_driver(driver, 3);
4357 SAFE_FREE(list);
4359 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4361 driver.info_3 = info;
4363 if ( DEBUGLEVEL >= 20 )
4364 dump_a_printer_driver( driver, 3 );
4366 return False;
4369 /****************************************************************************
4370 Actually delete the driver files. Make sure that
4371 printer_driver_files_in_use() return False before calling
4372 this.
4373 ****************************************************************************/
4375 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4377 int i = 0;
4378 char *s;
4379 connection_struct *conn;
4380 DATA_BLOB null_pw;
4381 NTSTATUS nt_status;
4382 fstring res_type;
4384 if ( !info_3 )
4385 return False;
4387 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4390 * Connect to the print$ share under the same account as the
4391 * user connected to the rpc pipe. Note we must be root to
4392 * do this.
4395 null_pw = data_blob( NULL, 0 );
4396 fstrcpy(res_type, "A:");
4397 become_root();
4398 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4399 unbecome_root();
4401 if ( !conn ) {
4402 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4403 return False;
4406 /* Save who we are - we are temporarily becoming the connection user. */
4408 if ( !become_user(conn, conn->vuid) ) {
4409 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4410 return False;
4413 /* now delete the files; must strip the '\print$' string from
4414 fron of path */
4416 if ( *info_3->driverpath ) {
4417 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4418 DEBUG(10,("deleting driverfile [%s]\n", s));
4419 unlink_internals(conn, 0, s);
4423 if ( *info_3->configfile ) {
4424 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4425 DEBUG(10,("deleting configfile [%s]\n", s));
4426 unlink_internals(conn, 0, s);
4430 if ( *info_3->datafile ) {
4431 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4432 DEBUG(10,("deleting datafile [%s]\n", s));
4433 unlink_internals(conn, 0, s);
4437 if ( *info_3->helpfile ) {
4438 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4439 DEBUG(10,("deleting helpfile [%s]\n", s));
4440 unlink_internals(conn, 0, s);
4444 /* check if we are done removing files */
4446 if ( info_3->dependentfiles ) {
4447 while ( *info_3->dependentfiles[i] ) {
4448 char *file;
4450 /* bypass the "\print$" portion of the path */
4452 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4453 DEBUG(10,("deleting dependent file [%s]\n", file));
4454 unlink_internals(conn, 0, file );
4457 i++;
4461 unbecome_user();
4463 return True;
4466 /****************************************************************************
4467 Remove a printer driver from the TDB. This assumes that the the driver was
4468 previously looked up.
4469 ***************************************************************************/
4471 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4472 uint32 version, BOOL delete_files )
4474 pstring key;
4475 const char *arch;
4476 TDB_DATA kbuf, dbuf;
4477 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4479 /* delete the tdb data first */
4481 arch = get_short_archi(info_3->environment);
4482 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4483 arch, version, info_3->name);
4485 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4486 key, delete_files ? "TRUE" : "FALSE" ));
4488 ctr.info_3 = info_3;
4489 dump_a_printer_driver( ctr, 3 );
4491 kbuf.dptr=key;
4492 kbuf.dsize=strlen(key)+1;
4494 /* check if the driver actually exists for this environment */
4496 dbuf = tdb_fetch( tdb_drivers, kbuf );
4497 if ( !dbuf.dptr ) {
4498 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4499 return WERR_UNKNOWN_PRINTER_DRIVER;
4502 SAFE_FREE( dbuf.dptr );
4504 /* ok... the driver exists so the delete should return success */
4506 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4507 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4508 return WERR_ACCESS_DENIED;
4512 * now delete any associated files if delete_files == True
4513 * even if this part failes, we return succes because the
4514 * driver doesn not exist any more
4517 if ( delete_files )
4518 delete_driver_files( info_3, user );
4521 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4523 return WERR_OK;
4526 /****************************************************************************
4527 Store a security desc for a printer.
4528 ****************************************************************************/
4530 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4532 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4533 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4534 prs_struct ps;
4535 TALLOC_CTX *mem_ctx = NULL;
4536 fstring key;
4537 WERROR status;
4539 mem_ctx = talloc_init("nt_printing_setsec");
4540 if (mem_ctx == NULL)
4541 return WERR_NOMEM;
4543 /* The old owner and group sids of the security descriptor are not
4544 present when new ACEs are added or removed by changing printer
4545 permissions through NT. If they are NULL in the new security
4546 descriptor then copy them over from the old one. */
4548 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4549 DOM_SID *owner_sid, *group_sid;
4550 SEC_ACL *dacl, *sacl;
4551 SEC_DESC *psd = NULL;
4552 size_t size;
4554 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4556 /* Pick out correct owner and group sids */
4558 owner_sid = secdesc_ctr->sec->owner_sid ?
4559 secdesc_ctr->sec->owner_sid :
4560 old_secdesc_ctr->sec->owner_sid;
4562 group_sid = secdesc_ctr->sec->grp_sid ?
4563 secdesc_ctr->sec->grp_sid :
4564 old_secdesc_ctr->sec->grp_sid;
4566 dacl = secdesc_ctr->sec->dacl ?
4567 secdesc_ctr->sec->dacl :
4568 old_secdesc_ctr->sec->dacl;
4570 sacl = secdesc_ctr->sec->sacl ?
4571 secdesc_ctr->sec->sacl :
4572 old_secdesc_ctr->sec->sacl;
4574 /* Make a deep copy of the security descriptor */
4576 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4577 owner_sid, group_sid,
4578 sacl,
4579 dacl,
4580 &size);
4582 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4585 if (!new_secdesc_ctr) {
4586 new_secdesc_ctr = secdesc_ctr;
4589 /* Store the security descriptor in a tdb */
4591 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4592 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4594 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4595 &ps, 1)) {
4596 status = WERR_BADFUNC;
4597 goto out;
4600 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4602 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4603 status = WERR_OK;
4604 } else {
4605 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4606 status = WERR_BADFUNC;
4609 /* Free malloc'ed memory */
4611 out:
4613 prs_mem_free(&ps);
4614 if (mem_ctx)
4615 talloc_destroy(mem_ctx);
4616 return status;
4619 /****************************************************************************
4620 Construct a default security descriptor buffer for a printer.
4621 ****************************************************************************/
4623 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4625 SEC_ACE ace[3];
4626 SEC_ACCESS sa;
4627 SEC_ACL *psa = NULL;
4628 SEC_DESC_BUF *sdb = NULL;
4629 SEC_DESC *psd = NULL;
4630 DOM_SID owner_sid;
4631 size_t sd_size;
4633 /* Create an ACE where Everyone is allowed to print */
4635 init_sec_access(&sa, PRINTER_ACE_PRINT);
4636 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4637 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4639 /* Make the security descriptor owned by the Administrators group
4640 on the PDC of the domain. */
4642 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4643 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4644 } else {
4646 /* Backup plan - make printer owned by admins.
4647 This should emulate a lanman printer as security
4648 settings can't be changed. */
4650 sid_copy(&owner_sid, get_global_sam_sid());
4651 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4654 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4655 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4656 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4657 SEC_ACE_FLAG_INHERIT_ONLY);
4659 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4660 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4661 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4663 /* The ACL revision number in rpc_secdesc.h differs from the one
4664 created by NT when setting ACE entries in printer
4665 descriptors. NT4 complains about the property being edited by a
4666 NT5 machine. */
4668 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4669 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4670 &owner_sid, NULL,
4671 NULL, psa, &sd_size);
4674 if (!psd) {
4675 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4676 return NULL;
4679 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4681 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4682 (unsigned int)sd_size));
4684 return sdb;
4687 /****************************************************************************
4688 Get a security desc for a printer.
4689 ****************************************************************************/
4691 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4693 prs_struct ps;
4694 fstring key;
4695 char *temp;
4697 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4698 printername = temp + 1;
4701 /* Fetch security descriptor from tdb */
4703 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4705 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4706 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4708 DEBUG(4,("using default secdesc for %s\n", printername));
4710 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4711 return False;
4714 /* Save default security descriptor for later */
4716 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4717 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4719 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4720 tdb_prs_store(tdb_printers, key, &ps);
4722 prs_mem_free(&ps);
4724 return True;
4727 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4728 this security descriptor has been created when winbindd was
4729 down. Take ownership of security descriptor. */
4731 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4732 DOM_SID owner_sid;
4734 /* Change sd owner to workgroup administrator */
4736 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4737 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4738 SEC_DESC *psd = NULL;
4739 size_t size;
4741 /* Create new sd */
4743 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4745 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4746 &owner_sid,
4747 (*secdesc_ctr)->sec->grp_sid,
4748 (*secdesc_ctr)->sec->sacl,
4749 (*secdesc_ctr)->sec->dacl,
4750 &size);
4752 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4754 /* Swap with other one */
4756 *secdesc_ctr = new_secdesc_ctr;
4758 /* Set it */
4760 nt_printing_setsec(printername, *secdesc_ctr);
4764 if (DEBUGLEVEL >= 10) {
4765 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4766 int i;
4768 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4769 printername, the_acl->num_aces));
4771 for (i = 0; i < the_acl->num_aces; i++) {
4772 fstring sid_str;
4774 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4776 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4777 the_acl->ace[i].type, the_acl->ace[i].flags,
4778 the_acl->ace[i].info.mask));
4782 prs_mem_free(&ps);
4783 return True;
4786 /* error code:
4787 0: everything OK
4788 1: level not implemented
4789 2: file doesn't exist
4790 3: can't allocate memory
4791 4: can't free memory
4792 5: non existant struct
4796 A printer and a printer driver are 2 different things.
4797 NT manages them separatelly, Samba does the same.
4798 Why ? Simply because it's easier and it makes sense !
4800 Now explanation: You have 3 printers behind your samba server,
4801 2 of them are the same make and model (laser A and B). But laser B
4802 has an 3000 sheet feeder and laser A doesn't such an option.
4803 Your third printer is an old dot-matrix model for the accounting :-).
4805 If the /usr/local/samba/lib directory (default dir), you will have
4806 5 files to describe all of this.
4808 3 files for the printers (1 by printer):
4809 NTprinter_laser A
4810 NTprinter_laser B
4811 NTprinter_accounting
4812 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4813 NTdriver_printer model X
4814 NTdriver_printer model Y
4816 jfm: I should use this comment for the text file to explain
4817 same thing for the forms BTW.
4818 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4822 /* Convert generic access rights to printer object specific access rights.
4823 It turns out that NT4 security descriptors use generic access rights and
4824 NT5 the object specific ones. */
4826 void map_printer_permissions(SEC_DESC *sd)
4828 int i;
4830 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4831 se_map_generic(&sd->dacl->ace[i].info.mask,
4832 &printer_generic_mapping);
4836 /****************************************************************************
4837 Check a user has permissions to perform the given operation. We use the
4838 permission constants defined in include/rpc_spoolss.h to check the various
4839 actions we perform when checking printer access.
4841 PRINTER_ACCESS_ADMINISTER:
4842 print_queue_pause, print_queue_resume, update_printer_sec,
4843 update_printer, spoolss_addprinterex_level_2,
4844 _spoolss_setprinterdata
4846 PRINTER_ACCESS_USE:
4847 print_job_start
4849 JOB_ACCESS_ADMINISTER:
4850 print_job_delete, print_job_pause, print_job_resume,
4851 print_queue_purge
4853 ****************************************************************************/
4854 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4856 SEC_DESC_BUF *secdesc = NULL;
4857 uint32 access_granted;
4858 NTSTATUS status;
4859 BOOL result;
4860 const char *pname;
4861 TALLOC_CTX *mem_ctx = NULL;
4862 extern struct current_user current_user;
4864 /* If user is NULL then use the current_user structure */
4866 if (!user)
4867 user = &current_user;
4869 /* Always allow root or printer admins to do anything */
4871 if (user->uid == 0 ||
4872 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4873 return True;
4876 /* Get printer name */
4878 pname = PRINTERNAME(snum);
4880 if (!pname || !*pname) {
4881 errno = EACCES;
4882 return False;
4885 /* Get printer security descriptor */
4887 if(!(mem_ctx = talloc_init("print_access_check"))) {
4888 errno = ENOMEM;
4889 return False;
4892 nt_printing_getsec(mem_ctx, pname, &secdesc);
4894 if (access_type == JOB_ACCESS_ADMINISTER) {
4895 SEC_DESC_BUF *parent_secdesc = secdesc;
4897 /* Create a child security descriptor to check permissions
4898 against. This is because print jobs are child objects
4899 objects of a printer. */
4901 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4903 /* Now this is the bit that really confuses me. The access
4904 type needs to be changed from JOB_ACCESS_ADMINISTER to
4905 PRINTER_ACCESS_ADMINISTER for this to work. Something
4906 to do with the child (job) object becoming like a
4907 printer?? -tpot */
4909 access_type = PRINTER_ACCESS_ADMINISTER;
4912 /* Check access */
4914 map_printer_permissions(secdesc->sec);
4916 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4917 &access_granted, &status);
4919 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4921 talloc_destroy(mem_ctx);
4923 if (!result)
4924 errno = EACCES;
4926 return result;
4929 /****************************************************************************
4930 Check the time parameters allow a print operation.
4931 *****************************************************************************/
4933 BOOL print_time_access_check(int snum)
4935 NT_PRINTER_INFO_LEVEL *printer = NULL;
4936 BOOL ok = False;
4937 time_t now = time(NULL);
4938 struct tm *t;
4939 uint32 mins;
4941 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4942 return False;
4944 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4945 ok = True;
4947 t = gmtime(&now);
4948 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4950 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4951 ok = True;
4953 free_a_printer(&printer, 2);
4955 if (!ok)
4956 errno = EACCES;
4958 return ok;