Fixes to check for wraps which could cause coredumps.
[Samba/gebeck_regimport.git] / source3 / printing / nt_printing.c
blob908bd9c887fd13f275934c2c2fef5d491fd1dfbd
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 = NULL;
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 unsigned int num_sections;
772 unsigned 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 if (section_table_bytes == 0)
787 goto error_exit;
789 SAFE_FREE(buf);
790 if ((buf=malloc(section_table_bytes)) == NULL) {
791 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
792 fname, section_table_bytes));
793 goto error_exit;
796 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
797 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
798 fname, byte_count));
799 goto error_exit;
802 /* Iterate the section table looking for the resource section ".rsrc" */
803 for (i = 0; i < num_sections; i++) {
804 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
806 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
807 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
808 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
810 if (section_bytes == 0)
811 goto error_exit;
813 SAFE_FREE(buf);
814 if ((buf=malloc(section_bytes)) == NULL) {
815 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
816 fname, section_bytes));
817 goto error_exit;
820 /* Seek to the start of the .rsrc section info */
821 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
822 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
823 fname, errno));
824 goto error_exit;
827 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
828 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
829 fname, byte_count));
830 goto error_exit;
833 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
834 goto error_exit;
836 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
837 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
838 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
839 /* Align to next long address */
840 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
842 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
843 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
844 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
846 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
847 fname, *major, *minor,
848 (*major>>16)&0xffff, *major&0xffff,
849 (*minor>>16)&0xffff, *minor&0xffff));
850 SAFE_FREE(buf);
851 return 1;
858 /* Version info not found, fall back to origin date/time */
859 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
860 SAFE_FREE(buf);
861 return 0;
863 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
864 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
865 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
866 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
867 /* At this point, we assume the file is in error. It still could be somthing
868 * else besides a NE file, but it unlikely at this point. */
869 goto error_exit;
872 /* Allocate a bit more space to speed up things */
873 SAFE_FREE(buf);
874 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
875 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
876 fname, PE_HEADER_SIZE));
877 goto error_exit;
880 /* This is a HACK! I got tired of trying to sort through the messy
881 * 'NE' file format. If anyone wants to clean this up please have at
882 * it, but this works. 'NE' files will eventually fade away. JRR */
883 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
884 /* Cover case that should not occur in a well formed 'NE' .dll file */
885 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
887 for(i=0; i<byte_count; i++) {
888 /* Fast skip past data that can't possibly match */
889 if (buf[i] != 'V') continue;
891 /* Potential match data crosses buf boundry, move it to beginning
892 * of buf, and fill the buf with as much as it will hold. */
893 if (i>byte_count-VS_VERSION_INFO_SIZE) {
894 int bc;
896 memcpy(buf, &buf[i], byte_count-i);
897 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
898 (byte_count-i))) < 0) {
900 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
901 fname, errno));
902 goto error_exit;
905 byte_count = bc + (byte_count - i);
906 if (byte_count<VS_VERSION_INFO_SIZE) break;
908 i = 0;
911 /* Check that the full signature string and the magic number that
912 * follows exist (not a perfect solution, but the chances that this
913 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
914 * twice, as it is simpler to read the code. */
915 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
916 /* Compute skip alignment to next long address */
917 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
918 sizeof(VS_SIGNATURE)) & 3;
919 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
921 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
922 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
923 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
924 fname, *major, *minor,
925 (*major>>16)&0xffff, *major&0xffff,
926 (*minor>>16)&0xffff, *minor&0xffff));
927 SAFE_FREE(buf);
928 return 1;
933 /* Version info not found, fall back to origin date/time */
934 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
935 SAFE_FREE(buf);
936 return 0;
938 } else
939 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
940 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
941 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
943 no_version_info:
944 SAFE_FREE(buf);
945 return 0;
947 error_exit:
948 SAFE_FREE(buf);
949 return -1;
952 /****************************************************************************
953 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
954 share one or more files. During the MS installation process files are checked
955 to insure that only a newer version of a shared file is installed over an
956 older version. There are several possibilities for this comparison. If there
957 is no previous version, the new one is newer (obviously). If either file is
958 missing the version info structure, compare the creation date (on Unix use
959 the modification date). Otherwise chose the numerically larger version number.
960 ****************************************************************************/
962 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
964 BOOL use_version = True;
965 pstring filepath;
967 uint32 new_major;
968 uint32 new_minor;
969 time_t new_create_time;
971 uint32 old_major;
972 uint32 old_minor;
973 time_t old_create_time;
975 int access_mode;
976 int action;
977 files_struct *fsp = NULL;
978 SMB_STRUCT_STAT st;
979 SMB_STRUCT_STAT stat_buf;
980 BOOL bad_path;
982 ZERO_STRUCT(st);
983 ZERO_STRUCT(stat_buf);
984 new_create_time = (time_t)0;
985 old_create_time = (time_t)0;
987 /* Get file version info (if available) for previous file (if it exists) */
988 pstrcpy(filepath, old_file);
990 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
992 fsp = open_file_shared(conn, filepath, &stat_buf,
993 SET_OPEN_MODE(DOS_OPEN_RDONLY),
994 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
995 0, 0, &access_mode, &action);
996 if (!fsp) {
997 /* Old file not found, so by definition new file is in fact newer */
998 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
999 filepath, errno));
1000 return True;
1002 } else {
1003 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1004 if (ret == -1) goto error_exit;
1006 if (!ret) {
1007 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1008 old_file));
1009 use_version = False;
1010 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1011 old_create_time = st.st_mtime;
1012 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1015 close_file(fsp, True);
1017 /* Get file version info (if available) for new file */
1018 pstrcpy(filepath, new_file);
1019 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1021 fsp = open_file_shared(conn, filepath, &stat_buf,
1022 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1023 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1024 0, 0, &access_mode, &action);
1025 if (!fsp) {
1026 /* New file not found, this shouldn't occur if the caller did its job */
1027 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1028 filepath, errno));
1029 goto error_exit;
1031 } else {
1032 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1033 if (ret == -1) goto error_exit;
1035 if (!ret) {
1036 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1037 new_file));
1038 use_version = False;
1039 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1040 new_create_time = st.st_mtime;
1041 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1044 close_file(fsp, True);
1046 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1047 /* Compare versions and choose the larger version number */
1048 if (new_major > old_major ||
1049 (new_major == old_major && new_minor > old_minor)) {
1051 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1052 return True;
1054 else {
1055 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1056 return False;
1059 } else {
1060 /* Compare modification time/dates and choose the newest time/date */
1061 if (new_create_time > old_create_time) {
1062 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1063 return True;
1065 else {
1066 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1067 return False;
1071 error_exit:
1072 if(fsp)
1073 close_file(fsp, True);
1074 return -1;
1077 /****************************************************************************
1078 Determine the correct cVersion associated with an architecture and driver
1079 ****************************************************************************/
1080 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1081 struct current_user *user, WERROR *perr)
1083 int cversion;
1084 int access_mode;
1085 int action;
1086 NTSTATUS nt_status;
1087 pstring driverpath;
1088 DATA_BLOB null_pw;
1089 fstring res_type;
1090 files_struct *fsp = NULL;
1091 BOOL bad_path;
1092 SMB_STRUCT_STAT st;
1093 connection_struct *conn;
1095 ZERO_STRUCT(st);
1097 *perr = WERR_INVALID_PARAM;
1099 /* If architecture is Windows 95/98/ME, the version is always 0. */
1100 if (strcmp(architecture, "WIN40") == 0) {
1101 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1102 *perr = WERR_OK;
1103 return 0;
1107 * Connect to the print$ share under the same account as the user connected
1108 * to the rpc pipe. Note we must still be root to do this.
1111 /* Null password is ok - we are already an authenticated user... */
1112 null_pw = data_blob(NULL, 0);
1113 fstrcpy(res_type, "A:");
1114 become_root();
1115 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1116 unbecome_root();
1118 if (conn == NULL) {
1119 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1120 *perr = ntstatus_to_werror(nt_status);
1121 return -1;
1124 /* We are temporarily becoming the connection user. */
1125 if (!become_user(conn, user->vuid)) {
1126 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1127 *perr = WERR_ACCESS_DENIED;
1128 return -1;
1131 /* Open the driver file (Portable Executable format) and determine the
1132 * deriver the cversion. */
1133 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1135 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1137 fsp = open_file_shared(conn, driverpath, &st,
1138 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1139 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1140 0, 0, &access_mode, &action);
1141 if (!fsp) {
1142 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1143 driverpath, errno));
1144 *perr = WERR_ACCESS_DENIED;
1145 goto error_exit;
1147 else {
1148 uint32 major;
1149 uint32 minor;
1150 int ret = get_file_version(fsp, driverpath, &major, &minor);
1151 if (ret == -1) goto error_exit;
1153 if (!ret) {
1154 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1155 goto error_exit;
1159 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1160 * for more details. Version in this case is not just the version of the
1161 * file, but the version in the sense of kernal mode (2) vs. user mode
1162 * (3) drivers. Other bits of the version fields are the version info.
1163 * JRR 010716
1165 cversion = major & 0x0000ffff;
1166 switch (cversion) {
1167 case 2: /* WinNT drivers */
1168 case 3: /* Win2K drivers */
1169 break;
1171 default:
1172 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1173 driverpath, cversion));
1174 goto error_exit;
1177 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1178 driverpath, major, minor));
1181 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1182 driverpath, cversion));
1184 close_file(fsp, True);
1185 close_cnum(conn, user->vuid);
1186 unbecome_user();
1187 *perr = WERR_OK;
1188 return cversion;
1191 error_exit:
1193 if(fsp)
1194 close_file(fsp, True);
1196 close_cnum(conn, user->vuid);
1197 unbecome_user();
1198 return -1;
1201 /****************************************************************************
1202 ****************************************************************************/
1203 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1204 struct current_user *user)
1206 const char *architecture;
1207 fstring new_name;
1208 char *p;
1209 int i;
1210 WERROR err;
1212 /* clean up the driver name.
1213 * we can get .\driver.dll
1214 * or worse c:\windows\system\driver.dll !
1216 /* using an intermediate string to not have overlaping memcpy()'s */
1217 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1218 fstrcpy(new_name, p+1);
1219 fstrcpy(driver->driverpath, new_name);
1222 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1223 fstrcpy(new_name, p+1);
1224 fstrcpy(driver->datafile, new_name);
1227 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1228 fstrcpy(new_name, p+1);
1229 fstrcpy(driver->configfile, new_name);
1232 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1233 fstrcpy(new_name, p+1);
1234 fstrcpy(driver->helpfile, new_name);
1237 if (driver->dependentfiles) {
1238 for (i=0; *driver->dependentfiles[i]; i++) {
1239 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1240 fstrcpy(new_name, p+1);
1241 fstrcpy(driver->dependentfiles[i], new_name);
1246 architecture = get_short_archi(driver->environment);
1248 /* jfm:7/16/2000 the client always sends the cversion=0.
1249 * The server should check which version the driver is by reading
1250 * the PE header of driver->driverpath.
1252 * For Windows 95/98 the version is 0 (so the value sent is correct)
1253 * For Windows NT (the architecture doesn't matter)
1254 * NT 3.1: cversion=0
1255 * NT 3.5/3.51: cversion=1
1256 * NT 4: cversion=2
1257 * NT2K: cversion=3
1259 if ((driver->cversion = get_correct_cversion( architecture,
1260 driver->driverpath, user, &err)) == -1)
1261 return err;
1263 return WERR_OK;
1266 /****************************************************************************
1267 ****************************************************************************/
1268 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1270 const char *architecture;
1271 fstring new_name;
1272 char *p;
1273 int i;
1274 WERROR err;
1276 /* clean up the driver name.
1277 * we can get .\driver.dll
1278 * or worse c:\windows\system\driver.dll !
1280 /* using an intermediate string to not have overlaping memcpy()'s */
1281 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1282 fstrcpy(new_name, p+1);
1283 fstrcpy(driver->driverpath, new_name);
1286 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1287 fstrcpy(new_name, p+1);
1288 fstrcpy(driver->datafile, new_name);
1291 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1292 fstrcpy(new_name, p+1);
1293 fstrcpy(driver->configfile, new_name);
1296 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1297 fstrcpy(new_name, p+1);
1298 fstrcpy(driver->helpfile, new_name);
1301 if (driver->dependentfiles) {
1302 for (i=0; *driver->dependentfiles[i]; i++) {
1303 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1304 fstrcpy(new_name, p+1);
1305 fstrcpy(driver->dependentfiles[i], new_name);
1310 architecture = get_short_archi(driver->environment);
1312 /* jfm:7/16/2000 the client always sends the cversion=0.
1313 * The server should check which version the driver is by reading
1314 * the PE header of driver->driverpath.
1316 * For Windows 95/98 the version is 0 (so the value sent is correct)
1317 * For Windows NT (the architecture doesn't matter)
1318 * NT 3.1: cversion=0
1319 * NT 3.5/3.51: cversion=1
1320 * NT 4: cversion=2
1321 * NT2K: cversion=3
1323 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1324 return err;
1326 return WERR_OK;
1329 /****************************************************************************
1330 ****************************************************************************/
1331 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1332 uint32 level, struct current_user *user)
1334 switch (level) {
1335 case 3:
1337 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1338 driver=driver_abstract.info_3;
1339 return clean_up_driver_struct_level_3(driver, user);
1341 case 6:
1343 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1344 driver=driver_abstract.info_6;
1345 return clean_up_driver_struct_level_6(driver, user);
1347 default:
1348 return WERR_INVALID_PARAM;
1352 /****************************************************************************
1353 This function sucks and should be replaced. JRA.
1354 ****************************************************************************/
1356 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1358 dst->cversion = src->version;
1360 fstrcpy( dst->name, src->name);
1361 fstrcpy( dst->environment, src->environment);
1362 fstrcpy( dst->driverpath, src->driverpath);
1363 fstrcpy( dst->datafile, src->datafile);
1364 fstrcpy( dst->configfile, src->configfile);
1365 fstrcpy( dst->helpfile, src->helpfile);
1366 fstrcpy( dst->monitorname, src->monitorname);
1367 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1368 dst->dependentfiles = src->dependentfiles;
1371 #if 0 /* Debugging function */
1373 static char* ffmt(unsigned char *c){
1374 int i;
1375 static char ffmt_str[17];
1377 for (i=0; i<16; i++) {
1378 if ((c[i] < ' ') || (c[i] > '~'))
1379 ffmt_str[i]='.';
1380 else
1381 ffmt_str[i]=c[i];
1383 ffmt_str[16]='\0';
1384 return ffmt_str;
1387 #endif
1389 /****************************************************************************
1390 ****************************************************************************/
1391 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1392 struct current_user *user, WERROR *perr)
1394 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1395 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1396 const char *architecture;
1397 pstring new_dir;
1398 pstring old_name;
1399 pstring new_name;
1400 DATA_BLOB null_pw;
1401 connection_struct *conn;
1402 NTSTATUS nt_status;
1403 pstring inbuf;
1404 pstring outbuf;
1405 fstring res_type;
1406 int ver = 0;
1407 int i;
1409 memset(inbuf, '\0', sizeof(inbuf));
1410 memset(outbuf, '\0', sizeof(outbuf));
1411 *perr = WERR_OK;
1413 if (level==3)
1414 driver=driver_abstract.info_3;
1415 else if (level==6) {
1416 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1417 driver = &converted_driver;
1418 } else {
1419 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1420 return False;
1423 architecture = get_short_archi(driver->environment);
1426 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1427 * Note we must be root to do this.
1430 null_pw = data_blob(NULL, 0);
1431 fstrcpy(res_type, "A:");
1432 become_root();
1433 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1434 unbecome_root();
1436 if (conn == NULL) {
1437 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1438 *perr = ntstatus_to_werror(nt_status);
1439 return False;
1443 * Save who we are - we are temporarily becoming the connection user.
1446 if (!become_user(conn, conn->vuid)) {
1447 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1448 return False;
1452 * make the directories version and version\driver_name
1453 * under the architecture directory.
1455 DEBUG(5,("Creating first directory\n"));
1456 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1457 mkdir_internal(conn, new_dir);
1459 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1460 * listed for this driver which has already been moved, skip it (note:
1461 * drivers may list the same file name several times. Then check if the
1462 * file already exists in archi\cversion\, if so, check that the version
1463 * info (or time stamps if version info is unavailable) is newer (or the
1464 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1465 * Otherwise, delete the file.
1467 * If a file is not moved to archi\cversion\ because of an error, all the
1468 * rest of the 'unmoved' driver files are removed from archi\. If one or
1469 * more of the driver's files was already moved to archi\cversion\, it
1470 * potentially leaves the driver in a partially updated state. Version
1471 * trauma will most likely occur if an client attempts to use any printer
1472 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1473 * done is appropriate... later JRR
1476 DEBUG(5,("Moving files now !\n"));
1478 if (driver->driverpath && strlen(driver->driverpath)) {
1479 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1480 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1481 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1482 NTSTATUS status;
1483 status = rename_internals(conn, new_name, old_name, True);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1486 new_name, old_name));
1487 *perr = ntstatus_to_werror(status);
1488 unlink_internals(conn, 0, new_name);
1489 ver = -1;
1492 else
1493 unlink_internals(conn, 0, new_name);
1496 if (driver->datafile && strlen(driver->datafile)) {
1497 if (!strequal(driver->datafile, driver->driverpath)) {
1498 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1499 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1500 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1501 NTSTATUS status;
1502 status = rename_internals(conn, new_name, old_name, True);
1503 if (!NT_STATUS_IS_OK(status)) {
1504 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1505 new_name, old_name));
1506 *perr = ntstatus_to_werror(status);
1507 unlink_internals(conn, 0, new_name);
1508 ver = -1;
1511 else
1512 unlink_internals(conn, 0, new_name);
1516 if (driver->configfile && strlen(driver->configfile)) {
1517 if (!strequal(driver->configfile, driver->driverpath) &&
1518 !strequal(driver->configfile, driver->datafile)) {
1519 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1520 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1521 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1522 NTSTATUS status;
1523 status = rename_internals(conn, new_name, old_name, True);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1526 new_name, old_name));
1527 *perr = ntstatus_to_werror(status);
1528 unlink_internals(conn, 0, new_name);
1529 ver = -1;
1532 else
1533 unlink_internals(conn, 0, new_name);
1537 if (driver->helpfile && strlen(driver->helpfile)) {
1538 if (!strequal(driver->helpfile, driver->driverpath) &&
1539 !strequal(driver->helpfile, driver->datafile) &&
1540 !strequal(driver->helpfile, driver->configfile)) {
1541 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1542 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1543 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1544 NTSTATUS status;
1545 status = rename_internals(conn, new_name, old_name, True);
1546 if (!NT_STATUS_IS_OK(status)) {
1547 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1548 new_name, old_name));
1549 *perr = ntstatus_to_werror(status);
1550 unlink_internals(conn, 0, new_name);
1551 ver = -1;
1554 else
1555 unlink_internals(conn, 0, new_name);
1559 if (driver->dependentfiles) {
1560 for (i=0; *driver->dependentfiles[i]; i++) {
1561 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1562 !strequal(driver->dependentfiles[i], driver->datafile) &&
1563 !strequal(driver->dependentfiles[i], driver->configfile) &&
1564 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1565 int j;
1566 for (j=0; j < i; j++) {
1567 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1568 goto NextDriver;
1572 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1573 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1574 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1575 NTSTATUS status;
1576 status = rename_internals(conn, new_name, old_name, True);
1577 if (!NT_STATUS_IS_OK(status)) {
1578 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1579 new_name, old_name));
1580 *perr = ntstatus_to_werror(status);
1581 unlink_internals(conn, 0, new_name);
1582 ver = -1;
1585 else
1586 unlink_internals(conn, 0, new_name);
1588 NextDriver: ;
1592 close_cnum(conn, user->vuid);
1593 unbecome_user();
1595 return ver == -1 ? False : True;
1598 /****************************************************************************
1599 ****************************************************************************/
1600 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1602 int len, buflen;
1603 const char *architecture;
1604 pstring directory;
1605 fstring temp_name;
1606 pstring key;
1607 char *buf;
1608 int i, ret;
1609 TDB_DATA kbuf, dbuf;
1611 architecture = get_short_archi(driver->environment);
1613 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1614 * \\server is added in the rpc server layer.
1615 * It does make sense to NOT store the server's name in the printer TDB.
1618 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1620 /* .inf files do not always list a file for each of the four standard files.
1621 * Don't prepend a path to a null filename, or client claims:
1622 * "The server on which the printer resides does not have a suitable
1623 * <printer driver name> printer driver installed. Click OK if you
1624 * wish to install the driver on your local machine."
1626 if (strlen(driver->driverpath)) {
1627 fstrcpy(temp_name, driver->driverpath);
1628 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1631 if (strlen(driver->datafile)) {
1632 fstrcpy(temp_name, driver->datafile);
1633 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1636 if (strlen(driver->configfile)) {
1637 fstrcpy(temp_name, driver->configfile);
1638 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1641 if (strlen(driver->helpfile)) {
1642 fstrcpy(temp_name, driver->helpfile);
1643 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1646 if (driver->dependentfiles) {
1647 for (i=0; *driver->dependentfiles[i]; i++) {
1648 fstrcpy(temp_name, driver->dependentfiles[i]);
1649 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1653 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1655 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1657 buf = NULL;
1658 len = buflen = 0;
1660 again:
1661 len = 0;
1662 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1663 driver->cversion,
1664 driver->name,
1665 driver->environment,
1666 driver->driverpath,
1667 driver->datafile,
1668 driver->configfile,
1669 driver->helpfile,
1670 driver->monitorname,
1671 driver->defaultdatatype);
1673 if (driver->dependentfiles) {
1674 for (i=0; *driver->dependentfiles[i]; i++) {
1675 len += tdb_pack(buf+len, buflen-len, "f",
1676 driver->dependentfiles[i]);
1680 if (len != buflen) {
1681 char *tb;
1683 tb = (char *)Realloc(buf, len);
1684 if (!tb) {
1685 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1686 ret = -1;
1687 goto done;
1689 else buf = tb;
1690 buflen = len;
1691 goto again;
1695 kbuf.dptr = key;
1696 kbuf.dsize = strlen(key)+1;
1697 dbuf.dptr = buf;
1698 dbuf.dsize = len;
1700 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1702 done:
1703 if (ret)
1704 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1706 SAFE_FREE(buf);
1707 return ret;
1710 /****************************************************************************
1711 ****************************************************************************/
1712 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1714 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1716 ZERO_STRUCT(info3);
1717 info3.cversion = driver->version;
1718 fstrcpy(info3.name,driver->name);
1719 fstrcpy(info3.environment,driver->environment);
1720 fstrcpy(info3.driverpath,driver->driverpath);
1721 fstrcpy(info3.datafile,driver->datafile);
1722 fstrcpy(info3.configfile,driver->configfile);
1723 fstrcpy(info3.helpfile,driver->helpfile);
1724 fstrcpy(info3.monitorname,driver->monitorname);
1725 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1726 info3.dependentfiles = driver->dependentfiles;
1728 return add_a_printer_driver_3(&info3);
1732 /****************************************************************************
1733 ****************************************************************************/
1734 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1736 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1738 ZERO_STRUCT(info);
1740 fstrcpy(info.name, driver);
1741 fstrcpy(info.defaultdatatype, "RAW");
1743 fstrcpy(info.driverpath, "");
1744 fstrcpy(info.datafile, "");
1745 fstrcpy(info.configfile, "");
1746 fstrcpy(info.helpfile, "");
1748 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1749 return WERR_NOMEM;
1751 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1752 fstrcpy(info.dependentfiles[0], "");
1754 *info_ptr = memdup(&info, sizeof(info));
1756 return WERR_OK;
1759 /****************************************************************************
1760 ****************************************************************************/
1761 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1763 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1764 TDB_DATA kbuf, dbuf;
1765 const char *architecture;
1766 int len = 0;
1767 int i;
1768 pstring key;
1770 ZERO_STRUCT(driver);
1772 architecture = get_short_archi(arch);
1774 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1776 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1777 version = 0;
1779 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1781 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1783 kbuf.dptr = key;
1784 kbuf.dsize = strlen(key)+1;
1786 dbuf = tdb_fetch(tdb_drivers, kbuf);
1787 if (!dbuf.dptr)
1788 return WERR_UNKNOWN_PRINTER_DRIVER;
1790 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1791 &driver.cversion,
1792 driver.name,
1793 driver.environment,
1794 driver.driverpath,
1795 driver.datafile,
1796 driver.configfile,
1797 driver.helpfile,
1798 driver.monitorname,
1799 driver.defaultdatatype);
1801 i=0;
1802 while (len < dbuf.dsize) {
1803 fstring *tddfs;
1805 tddfs = (fstring *)Realloc(driver.dependentfiles,
1806 sizeof(fstring)*(i+2));
1807 if (tddfs == NULL) {
1808 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1809 break;
1811 else driver.dependentfiles = tddfs;
1813 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1814 &driver.dependentfiles[i]);
1815 i++;
1818 if (driver.dependentfiles != NULL)
1819 fstrcpy(driver.dependentfiles[i], "");
1821 SAFE_FREE(dbuf.dptr);
1823 if (len != dbuf.dsize) {
1824 SAFE_FREE(driver.dependentfiles);
1826 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1829 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1831 return WERR_OK;
1834 /****************************************************************************
1835 Debugging function, dump at level 6 the struct in the logs.
1836 ****************************************************************************/
1838 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1840 uint32 result;
1841 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1842 int i;
1844 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1846 switch (level)
1848 case 3:
1850 if (driver.info_3 == NULL)
1851 result=5;
1852 else {
1853 info3=driver.info_3;
1855 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1856 DEBUGADD(20,("name:[%s]\n", info3->name));
1857 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1858 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1859 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1860 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1861 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1862 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1863 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1865 for (i=0; info3->dependentfiles &&
1866 *info3->dependentfiles[i]; i++) {
1867 DEBUGADD(20,("dependentfile:[%s]\n",
1868 info3->dependentfiles[i]));
1870 result=0;
1872 break;
1874 default:
1875 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1876 result=1;
1877 break;
1880 return result;
1883 /****************************************************************************
1884 ****************************************************************************/
1885 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1887 int len = 0;
1889 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1891 if (!nt_devmode)
1892 return len;
1894 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1895 nt_devmode->devicename,
1896 nt_devmode->formname,
1898 nt_devmode->specversion,
1899 nt_devmode->driverversion,
1900 nt_devmode->size,
1901 nt_devmode->driverextra,
1902 nt_devmode->orientation,
1903 nt_devmode->papersize,
1904 nt_devmode->paperlength,
1905 nt_devmode->paperwidth,
1906 nt_devmode->scale,
1907 nt_devmode->copies,
1908 nt_devmode->defaultsource,
1909 nt_devmode->printquality,
1910 nt_devmode->color,
1911 nt_devmode->duplex,
1912 nt_devmode->yresolution,
1913 nt_devmode->ttoption,
1914 nt_devmode->collate,
1915 nt_devmode->logpixels,
1917 nt_devmode->fields,
1918 nt_devmode->bitsperpel,
1919 nt_devmode->pelswidth,
1920 nt_devmode->pelsheight,
1921 nt_devmode->displayflags,
1922 nt_devmode->displayfrequency,
1923 nt_devmode->icmmethod,
1924 nt_devmode->icmintent,
1925 nt_devmode->mediatype,
1926 nt_devmode->dithertype,
1927 nt_devmode->reserved1,
1928 nt_devmode->reserved2,
1929 nt_devmode->panningwidth,
1930 nt_devmode->panningheight,
1931 nt_devmode->private);
1934 if (nt_devmode->private) {
1935 len += tdb_pack(buf+len, buflen-len, "B",
1936 nt_devmode->driverextra,
1937 nt_devmode->private);
1940 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1942 return len;
1945 /****************************************************************************
1946 Pack all values in all printer keys
1947 ***************************************************************************/
1949 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1951 int len = 0;
1952 int i, j;
1953 REGISTRY_VALUE *val;
1954 REGVAL_CTR *val_ctr;
1955 pstring path;
1956 int num_values;
1958 if ( !data )
1959 return 0;
1961 /* loop over all keys */
1963 for ( i=0; i<data->num_keys; i++ ) {
1964 val_ctr = &data->keys[i].values;
1965 num_values = regval_ctr_numvals( val_ctr );
1967 /* loop over all values */
1969 for ( j=0; j<num_values; j++ ) {
1970 /* pathname should be stored as <key>\<value> */
1972 val = regval_ctr_specific_value( val_ctr, j );
1973 pstrcpy( path, data->keys[i].name );
1974 pstrcat( path, "\\" );
1975 pstrcat( path, regval_name(val) );
1977 len += tdb_pack(buf+len, buflen-len, "pPdB",
1978 val,
1979 path,
1980 regval_type(val),
1981 regval_size(val),
1982 regval_data_p(val) );
1987 /* terminator */
1989 len += tdb_pack(buf+len, buflen-len, "p", NULL);
1991 return len;
1995 /****************************************************************************
1996 Delete a printer - this just deletes the printer info file, any open
1997 handles are not affected.
1998 ****************************************************************************/
2000 uint32 del_a_printer(char *sharename)
2002 pstring key;
2003 TDB_DATA kbuf;
2005 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2007 kbuf.dptr=key;
2008 kbuf.dsize=strlen(key)+1;
2010 tdb_delete(tdb_printers, kbuf);
2011 return 0;
2014 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2015 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, const char* sharename);
2016 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2017 /****************************************************************************
2018 ****************************************************************************/
2019 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2021 pstring key;
2022 char *buf;
2023 int buflen, len;
2024 WERROR ret;
2025 TDB_DATA kbuf, dbuf;
2028 * in addprinter: no servername and the printer is the name
2029 * in setprinter: servername is \\server
2030 * and printer is \\server\\printer
2032 * Samba manages only local printers.
2033 * we currently don't support things like path=\\other_server\printer
2036 if (info->servername[0]!='\0') {
2037 trim_string(info->printername, info->servername, NULL);
2038 trim_char(info->printername, '\\', '\0');
2039 info->servername[0]='\0';
2043 * JFM: one day I'll forget.
2044 * below that's info->portname because that's the SAMBA sharename
2045 * and I made NT 'thinks' it's the portname
2046 * the info->sharename is the thing you can name when you add a printer
2047 * that's the short-name when you create shared printer for 95/98
2048 * So I've made a limitation in SAMBA: you can only have 1 printer model
2049 * behind a SAMBA share.
2052 buf = NULL;
2053 buflen = 0;
2055 again:
2056 len = 0;
2057 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2058 info->attributes,
2059 info->priority,
2060 info->default_priority,
2061 info->starttime,
2062 info->untiltime,
2063 info->status,
2064 info->cjobs,
2065 info->averageppm,
2066 info->changeid,
2067 info->c_setprinter,
2068 info->setuptime,
2069 info->servername,
2070 info->printername,
2071 info->sharename,
2072 info->portname,
2073 info->drivername,
2074 info->comment,
2075 info->location,
2076 info->sepfile,
2077 info->printprocessor,
2078 info->datatype,
2079 info->parameters);
2081 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2083 len += pack_values( &info->data, buf+len, buflen-len );
2085 if (buflen != len) {
2086 char *tb;
2088 tb = (char *)Realloc(buf, len);
2089 if (!tb) {
2090 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2091 ret = WERR_NOMEM;
2092 goto done;
2094 else buf = tb;
2095 buflen = len;
2096 goto again;
2100 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2102 kbuf.dptr = key;
2103 kbuf.dsize = strlen(key)+1;
2104 dbuf.dptr = buf;
2105 dbuf.dsize = len;
2107 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2109 done:
2110 if (!W_ERROR_IS_OK(ret))
2111 DEBUG(8, ("error updating printer to tdb on disk\n"));
2113 SAFE_FREE(buf);
2115 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2116 info->sharename, info->drivername, info->portname, len));
2118 return ret;
2122 /****************************************************************************
2123 Malloc and return an NT devicemode.
2124 ****************************************************************************/
2126 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2129 char adevice[MAXDEVICENAME];
2130 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2132 if (nt_devmode == NULL) {
2133 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2134 return NULL;
2137 ZERO_STRUCTP(nt_devmode);
2139 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2140 fstrcpy(nt_devmode->devicename, adevice);
2142 fstrcpy(nt_devmode->formname, "Letter");
2144 nt_devmode->specversion = 0x0401;
2145 nt_devmode->driverversion = 0x0400;
2146 nt_devmode->size = 0x00DC;
2147 nt_devmode->driverextra = 0x0000;
2148 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2149 DEFAULTSOURCE | COPIES | SCALE |
2150 PAPERSIZE | ORIENTATION;
2151 nt_devmode->orientation = 1;
2152 nt_devmode->papersize = PAPER_LETTER;
2153 nt_devmode->paperlength = 0;
2154 nt_devmode->paperwidth = 0;
2155 nt_devmode->scale = 0x64;
2156 nt_devmode->copies = 1;
2157 nt_devmode->defaultsource = BIN_FORMSOURCE;
2158 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2159 nt_devmode->color = COLOR_MONOCHROME;
2160 nt_devmode->duplex = DUP_SIMPLEX;
2161 nt_devmode->yresolution = 0;
2162 nt_devmode->ttoption = TT_SUBDEV;
2163 nt_devmode->collate = COLLATE_FALSE;
2164 nt_devmode->icmmethod = 0;
2165 nt_devmode->icmintent = 0;
2166 nt_devmode->mediatype = 0;
2167 nt_devmode->dithertype = 0;
2169 /* non utilisés par un driver d'imprimante */
2170 nt_devmode->logpixels = 0;
2171 nt_devmode->bitsperpel = 0;
2172 nt_devmode->pelswidth = 0;
2173 nt_devmode->pelsheight = 0;
2174 nt_devmode->displayflags = 0;
2175 nt_devmode->displayfrequency = 0;
2176 nt_devmode->reserved1 = 0;
2177 nt_devmode->reserved2 = 0;
2178 nt_devmode->panningwidth = 0;
2179 nt_devmode->panningheight = 0;
2181 nt_devmode->private = NULL;
2182 return nt_devmode;
2185 /****************************************************************************
2186 Deepcopy an NT devicemode.
2187 ****************************************************************************/
2189 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2191 NT_DEVICEMODE *new_nt_devicemode = NULL;
2193 if ( !nt_devicemode )
2194 return NULL;
2196 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2197 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2198 return NULL;
2201 new_nt_devicemode->private = NULL;
2202 if (nt_devicemode->private != NULL) {
2203 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2204 SAFE_FREE(new_nt_devicemode);
2205 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2206 return NULL;
2210 return new_nt_devicemode;
2213 /****************************************************************************
2214 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2215 ****************************************************************************/
2217 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2219 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2221 if(nt_devmode == NULL)
2222 return;
2224 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2226 SAFE_FREE(nt_devmode->private);
2227 SAFE_FREE(*devmode_ptr);
2230 /****************************************************************************
2231 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2232 ****************************************************************************/
2233 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2235 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2236 NT_PRINTER_DATA *data;
2237 int i;
2239 if ( !info )
2240 return;
2242 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2244 free_nt_devicemode(&info->devmode);
2246 /* clean up all registry keys */
2248 data = &info->data;
2249 for ( i=0; i<data->num_keys; i++ ) {
2250 SAFE_FREE( data->keys[i].name );
2251 regval_ctr_destroy( &data->keys[i].values );
2253 SAFE_FREE( data->keys );
2255 /* finally the top level structure */
2257 SAFE_FREE( *info_ptr );
2261 /****************************************************************************
2262 ****************************************************************************/
2263 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2265 int len = 0;
2266 int extra_len = 0;
2267 NT_DEVICEMODE devmode;
2269 ZERO_STRUCT(devmode);
2271 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2273 if (!*nt_devmode) return len;
2275 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2276 devmode.devicename,
2277 devmode.formname,
2279 &devmode.specversion,
2280 &devmode.driverversion,
2281 &devmode.size,
2282 &devmode.driverextra,
2283 &devmode.orientation,
2284 &devmode.papersize,
2285 &devmode.paperlength,
2286 &devmode.paperwidth,
2287 &devmode.scale,
2288 &devmode.copies,
2289 &devmode.defaultsource,
2290 &devmode.printquality,
2291 &devmode.color,
2292 &devmode.duplex,
2293 &devmode.yresolution,
2294 &devmode.ttoption,
2295 &devmode.collate,
2296 &devmode.logpixels,
2298 &devmode.fields,
2299 &devmode.bitsperpel,
2300 &devmode.pelswidth,
2301 &devmode.pelsheight,
2302 &devmode.displayflags,
2303 &devmode.displayfrequency,
2304 &devmode.icmmethod,
2305 &devmode.icmintent,
2306 &devmode.mediatype,
2307 &devmode.dithertype,
2308 &devmode.reserved1,
2309 &devmode.reserved2,
2310 &devmode.panningwidth,
2311 &devmode.panningheight,
2312 &devmode.private);
2314 if (devmode.private) {
2315 /* the len in tdb_unpack is an int value and
2316 * devmode.driverextra is only a short
2318 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2319 devmode.driverextra=(uint16)extra_len;
2321 /* check to catch an invalid TDB entry so we don't segfault */
2322 if (devmode.driverextra == 0) {
2323 devmode.private = NULL;
2327 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2329 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2330 if (devmode.private)
2331 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2333 return len;
2336 /****************************************************************************
2337 Allocate and initialize a new slot.
2338 ***************************************************************************/
2340 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2342 NT_PRINTER_KEY *d;
2343 int key_index;
2345 if ( !data || !name )
2346 return -1;
2348 /* allocate another slot in the NT_PRINTER_KEY array */
2350 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2351 if ( d )
2352 data->keys = d;
2354 key_index = data->num_keys;
2356 /* initialze new key */
2358 data->num_keys++;
2359 data->keys[key_index].name = strdup( name );
2361 ZERO_STRUCTP( &data->keys[key_index].values );
2363 regval_ctr_init( &data->keys[key_index].values );
2365 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2367 return key_index;
2370 /****************************************************************************
2371 search for a registry key name in the existing printer data
2372 ***************************************************************************/
2374 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2376 int key_index = -1;
2377 int i;
2379 if ( !data || !name )
2380 return -1;
2382 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2384 /* loop over all existing keys */
2386 for ( i=0; i<data->num_keys; i++ ) {
2387 if ( strequal(data->keys[i].name, name) ) {
2388 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2389 key_index = i;
2390 break;
2395 return key_index;
2398 /****************************************************************************
2399 ***************************************************************************/
2401 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2403 int i, j;
2404 int key_len;
2405 int num_subkeys = 0;
2406 char *p;
2407 fstring *ptr, *subkeys_ptr = NULL;
2408 fstring subkeyname;
2410 if ( !data )
2411 return 0;
2413 for ( i=0; i<data->num_keys; i++ ) {
2414 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2415 /* match sure it is a subkey and not the key itself */
2417 key_len = strlen( key );
2418 if ( strlen(data->keys[i].name) == key_len )
2419 continue;
2421 /* get subkey path */
2423 p = data->keys[i].name + key_len;
2424 if ( *p == '\\' )
2425 p++;
2426 fstrcpy( subkeyname, p );
2427 if ( (p = strchr( subkeyname, '\\' )) )
2428 *p = '\0';
2430 /* don't add a key more than once */
2432 for ( j=0; j<num_subkeys; j++ ) {
2433 if ( strequal( subkeys_ptr[j], subkeyname ) )
2434 break;
2437 if ( j != num_subkeys )
2438 continue;
2440 /* found a match, so allocate space and copy the name */
2442 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2443 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2444 num_subkeys+1));
2445 SAFE_FREE( subkeys );
2446 return 0;
2449 subkeys_ptr = ptr;
2450 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2451 num_subkeys++;
2456 /* tag of the end */
2458 if (num_subkeys)
2459 fstrcpy(subkeys_ptr[num_subkeys], "" );
2461 *subkeys = subkeys_ptr;
2463 return num_subkeys;
2466 #ifdef HAVE_ADS
2467 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2468 const char *sz)
2470 smb_ucs2_t conv_str[1024];
2471 size_t str_size;
2473 regval_ctr_delvalue(ctr, val_name);
2474 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2475 STR_TERMINATE | STR_NOALIGN);
2476 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2477 (char *) conv_str, str_size);
2480 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2481 uint32 dword)
2483 regval_ctr_delvalue(ctr, val_name);
2484 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2485 (char *) &dword, sizeof(dword));
2488 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2489 BOOL b)
2491 uint8 bin_bool = (b ? 1 : 0);
2492 regval_ctr_delvalue(ctr, val_name);
2493 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2494 (char *) &bin_bool, sizeof(bin_bool));
2497 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2498 const char *multi_sz)
2500 smb_ucs2_t *conv_strs = NULL;
2501 size_t str_size;
2503 /* a multi-sz has to have a null string terminator, i.e., the last
2504 string must be followed by two nulls */
2505 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2506 conv_strs = calloc(str_size, 1);
2508 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2509 STR_TERMINATE | STR_NOALIGN);
2511 regval_ctr_delvalue(ctr, val_name);
2512 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2513 (char *) conv_strs, str_size);
2514 safe_free(conv_strs);
2518 /****************************************************************************
2519 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2521 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2522 * @return BOOL indicating success or failure
2523 ***************************************************************************/
2525 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2527 REGVAL_CTR *ctr = NULL;
2528 fstring longname;
2529 char *allocated_string = NULL;
2530 const char *ascii_str;
2531 int i;
2533 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2534 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2535 ctr = &info2->data.keys[i].values;
2537 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2538 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2540 get_myfullname(longname);
2541 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2543 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2544 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2545 SAFE_FREE(allocated_string);
2547 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2548 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2549 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2550 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2551 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2552 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2553 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2554 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2555 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2557 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2558 (info2->attributes &
2559 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2561 switch (info2->attributes & 0x3) {
2562 case 0:
2563 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2564 break;
2565 case 1:
2566 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2567 break;
2568 case 2:
2569 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2570 break;
2571 default:
2572 ascii_str = "unknown";
2574 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2576 return True;
2579 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid)
2581 int i;
2582 REGVAL_CTR *ctr=NULL;
2584 /* find the DsSpooler key */
2585 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2586 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2587 ctr = &info2->data.keys[i].values;
2589 regval_ctr_delvalue(ctr, "objectGUID");
2590 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2591 (char *) &guid, sizeof(GUID));
2594 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2596 ADS_STATUS ads_rc;
2597 TALLOC_CTX *ctx = talloc_init("publish_it");
2598 ADS_MODLIST mods = ads_init_mods(ctx);
2599 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2600 char *srv_dn_utf8, **srv_cn_utf8;
2601 void *res = NULL;
2602 ADS_STRUCT *ads;
2603 const char *attrs[] = {"objectGUID", NULL};
2604 GUID guid;
2605 WERROR win_rc = WERR_OK;
2607 ZERO_STRUCT(guid);
2608 /* set the DsSpooler info and attributes */
2609 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2610 return WERR_NOMEM;
2611 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2612 win_rc = mod_a_printer(*printer, 2);
2613 if (!W_ERROR_IS_OK(win_rc)) {
2614 DEBUG(3, ("err %d saving data\n",
2615 W_ERROR_V(win_rc)));
2616 return win_rc;
2619 /* Build the ads mods */
2620 get_local_printer_publishing_data(ctx, &mods,
2621 &printer->info_2->data);
2622 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2623 printer->info_2->sharename);
2625 /* initial ads structure */
2627 ads = ads_init(NULL, NULL, NULL);
2628 if (!ads) {
2629 DEBUG(3, ("ads_init() failed\n"));
2630 return WERR_SERVER_UNAVAILABLE;
2632 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2633 SAFE_FREE(ads->auth.password);
2634 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2635 NULL, NULL);
2637 /* ads_connect() will find the DC for us */
2638 ads_rc = ads_connect(ads);
2639 if (!ADS_ERR_OK(ads_rc)) {
2640 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2641 ads_destroy(&ads);
2642 return WERR_ACCESS_DENIED;
2645 /* figure out where to publish */
2646 ads_find_machine_acct(ads, &res, global_myname());
2648 /* We use ldap_get_dn here as we need the answer
2649 * in utf8 to call ldap_explode_dn(). JRA. */
2651 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2652 if (!srv_dn_utf8) {
2653 ads_destroy(&ads);
2654 return WERR_SERVER_UNAVAILABLE;
2656 ads_msgfree(ads, res);
2657 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2658 if (!srv_cn_utf8) {
2659 ldap_memfree(srv_dn_utf8);
2660 ads_destroy(&ads);
2661 return WERR_SERVER_UNAVAILABLE;
2663 /* Now convert to CH_UNIX. */
2664 if (pull_utf8_allocate((void **) &srv_dn, srv_dn_utf8) == (size_t)-1) {
2665 ldap_memfree(srv_dn_utf8);
2666 ldap_memfree(srv_cn_utf8);
2667 ads_destroy(&ads);
2668 return WERR_SERVER_UNAVAILABLE;
2670 if (pull_utf8_allocate((void **) &srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2671 ldap_memfree(srv_dn_utf8);
2672 ldap_memfree(srv_cn_utf8);
2673 ads_destroy(&ads);
2674 SAFE_FREE(srv_dn);
2675 return WERR_SERVER_UNAVAILABLE;
2678 ldap_memfree(srv_dn_utf8);
2679 ldap_memfree(srv_cn_utf8);
2681 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2682 printer->info_2->sharename, srv_dn);
2684 SAFE_FREE(srv_dn);
2685 SAFE_FREE(srv_cn_0);
2687 /* publish it */
2688 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2689 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2690 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2692 /* retreive the guid and store it locally */
2693 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2694 ads_memfree(ads, prt_dn);
2695 ads_pull_guid(ads, res, &guid);
2696 ads_msgfree(ads, res);
2697 store_printer_guid(printer->info_2, guid);
2698 win_rc = mod_a_printer(*printer, 2);
2701 safe_free(prt_dn);
2702 ads_destroy(&ads);
2704 return WERR_OK;
2707 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2709 ADS_STATUS ads_rc;
2710 ADS_STRUCT *ads;
2711 void *res;
2712 char *prt_dn = NULL;
2713 WERROR win_rc;
2715 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2716 win_rc = mod_a_printer(*printer, 2);
2717 if (!W_ERROR_IS_OK(win_rc)) {
2718 DEBUG(3, ("err %d saving data\n",
2719 W_ERROR_V(win_rc)));
2720 return win_rc;
2723 ads = ads_init(NULL, NULL, NULL);
2724 if (!ads) {
2725 DEBUG(3, ("ads_init() failed\n"));
2726 return WERR_SERVER_UNAVAILABLE;
2728 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2729 SAFE_FREE(ads->auth.password);
2730 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2731 NULL, NULL);
2733 /* ads_connect() will find the DC for us */
2734 ads_rc = ads_connect(ads);
2735 if (!ADS_ERR_OK(ads_rc)) {
2736 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2737 ads_destroy(&ads);
2738 return WERR_ACCESS_DENIED;
2741 /* remove the printer from the directory */
2742 ads_rc = ads_find_printer_on_server(ads, &res,
2743 printer->info_2->sharename, global_myname());
2744 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2745 prt_dn = ads_get_dn(ads, res);
2746 ads_msgfree(ads, res);
2747 ads_rc = ads_del_dn(ads, prt_dn);
2748 ads_memfree(ads, prt_dn);
2751 ads_destroy(&ads);
2752 return WERR_OK;
2755 /****************************************************************************
2756 * Publish a printer in the directory
2758 * @param snum describing printer service
2759 * @return WERROR indicating status of publishing
2760 ***************************************************************************/
2762 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2764 NT_PRINTER_INFO_LEVEL *printer = NULL;
2765 WERROR win_rc;
2767 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2768 if (!W_ERROR_IS_OK(win_rc))
2769 return win_rc;
2771 switch(action) {
2772 case SPOOL_DS_PUBLISH:
2773 case SPOOL_DS_UPDATE:
2774 win_rc = publish_it(printer);
2775 break;
2776 case SPOOL_DS_UNPUBLISH:
2777 win_rc = unpublish_it(printer);
2778 break;
2779 default:
2780 win_rc = WERR_NOT_SUPPORTED;
2784 free_a_printer(&printer, 2);
2785 return win_rc;
2788 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2790 NT_PRINTER_INFO_LEVEL *printer = NULL;
2791 REGVAL_CTR *ctr;
2792 REGISTRY_VALUE *guid_val;
2793 WERROR win_rc;
2794 int i;
2797 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2798 if (!W_ERROR_IS_OK(win_rc))
2799 return False;
2801 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2802 return False;
2804 if ((i = lookup_printerkey(&printer->info_2->data,
2805 SPOOL_DSSPOOLER_KEY)) < 0)
2806 return False;
2808 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2809 return False;
2812 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2813 return False;
2816 if (regval_size(guid_val) == sizeof(GUID))
2817 memcpy(guid, regval_data_p(guid_val), sizeof(GUID));
2819 return True;
2822 #else
2823 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2825 return WERR_OK;
2827 BOOL is_printer_published(Printer_entry *print_hnd, int snum, GUID *guid)
2829 return False;
2831 #endif
2832 /****************************************************************************
2833 ***************************************************************************/
2835 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2837 NT_PRINTER_DATA *data;
2838 int i;
2839 int removed_keys = 0;
2840 int empty_slot;
2842 data = &p2->data;
2843 empty_slot = data->num_keys;
2845 if ( !key )
2846 return WERR_INVALID_PARAM;
2848 /* remove all keys */
2850 if ( !strlen(key) ) {
2851 for ( i=0; i<data->num_keys; i++ ) {
2852 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2853 data->keys[i].name));
2855 SAFE_FREE( data->keys[i].name );
2856 regval_ctr_destroy( &data->keys[i].values );
2859 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2860 p2->printername ));
2862 SAFE_FREE( data->keys );
2863 ZERO_STRUCTP( data );
2865 return WERR_OK;
2868 /* remove a specific key (and all subkeys) */
2870 for ( i=0; i<data->num_keys; i++ ) {
2871 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2872 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2873 data->keys[i].name));
2875 SAFE_FREE( data->keys[i].name );
2876 regval_ctr_destroy( &data->keys[i].values );
2878 /* mark the slot as empty */
2880 ZERO_STRUCTP( &data->keys[i] );
2884 /* find the first empty slot */
2886 for ( i=0; i<data->num_keys; i++ ) {
2887 if ( !data->keys[i].name ) {
2888 empty_slot = i;
2889 removed_keys++;
2890 break;
2894 if ( i == data->num_keys )
2895 /* nothing was removed */
2896 return WERR_INVALID_PARAM;
2898 /* move everything down */
2900 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2901 if ( data->keys[i].name ) {
2902 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2903 ZERO_STRUCTP( &data->keys[i] );
2904 empty_slot++;
2905 removed_keys++;
2909 /* update count */
2911 data->num_keys -= removed_keys;
2913 /* sanity check to see if anything is left */
2915 if ( !data->num_keys ) {
2916 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2918 SAFE_FREE( data->keys );
2919 ZERO_STRUCTP( data );
2922 return WERR_OK;
2925 /****************************************************************************
2926 ***************************************************************************/
2928 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2930 WERROR result = WERR_OK;
2931 int key_index;
2933 /* we must have names on non-zero length */
2935 if ( !key || !*key|| !value || !*value )
2936 return WERR_INVALID_NAME;
2938 /* find the printer key first */
2940 key_index = lookup_printerkey( &p2->data, key );
2941 if ( key_index == -1 )
2942 return WERR_OK;
2944 /* make sure the value exists so we can return the correct error code */
2946 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2947 return WERR_BADFILE;
2949 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2951 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2952 key, value ));
2954 return result;
2957 /****************************************************************************
2958 ***************************************************************************/
2960 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
2961 uint32 type, uint8 *data, int real_len )
2963 WERROR result = WERR_OK;
2964 int key_index;
2966 /* we must have names on non-zero length */
2968 if ( !key || !*key|| !value || !*value )
2969 return WERR_INVALID_NAME;
2971 /* find the printer key first */
2973 key_index = lookup_printerkey( &p2->data, key );
2974 if ( key_index == -1 )
2975 key_index = add_new_printer_key( &p2->data, key );
2977 if ( key_index == -1 )
2978 return WERR_NOMEM;
2980 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2981 type, (const char *)data, real_len );
2983 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2984 key, value, type, real_len ));
2986 return result;
2989 /****************************************************************************
2990 ***************************************************************************/
2992 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2994 int key_index;
2996 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2997 return NULL;
2999 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3000 key, value ));
3002 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3005 /****************************************************************************
3006 Unpack a list of registry values frem the TDB
3007 ***************************************************************************/
3009 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3011 int len = 0;
3012 uint32 type;
3013 pstring string, valuename, keyname;
3014 char *str;
3015 int size;
3016 uint8 *data_p;
3017 REGISTRY_VALUE *regval_p;
3018 int key_index;
3020 /* add the "PrinterDriverData" key first for performance reasons */
3022 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3024 /* loop and unpack the rest of the registry values */
3026 while ( True ) {
3028 /* check to see if there are any more registry values */
3030 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
3031 if ( !regval_p )
3032 break;
3034 /* unpack the next regval */
3036 len += tdb_unpack(buf+len, buflen-len, "fdB",
3037 string,
3038 &type,
3039 &size,
3040 &data_p);
3043 * break of the keyname from the value name.
3044 * Should only be one '\' in the string returned.
3047 str = strrchr( string, '\\');
3049 /* Put in "PrinterDriverData" is no key specified */
3051 if ( !str ) {
3052 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3053 pstrcpy( valuename, string );
3055 else {
3056 *str = '\0';
3057 pstrcpy( keyname, string );
3058 pstrcpy( valuename, str+1 );
3061 /* see if we need a new key */
3063 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3064 key_index = add_new_printer_key( printer_data, keyname );
3066 if ( key_index == -1 ) {
3067 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3068 keyname));
3069 break;
3072 /* add the new value */
3074 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3076 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3078 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3081 return len;
3084 /****************************************************************************
3085 ***************************************************************************/
3087 static void map_to_os2_driver(fstring drivername)
3089 static BOOL initialised=False;
3090 static fstring last_from,last_to;
3091 char *mapfile = lp_os2_driver_map();
3092 char **lines = NULL;
3093 int numlines = 0;
3094 int i;
3096 if (!strlen(drivername))
3097 return;
3099 if (!*mapfile)
3100 return;
3102 if (!initialised) {
3103 *last_from = *last_to = 0;
3104 initialised = True;
3107 if (strequal(drivername,last_from)) {
3108 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3109 fstrcpy(drivername,last_to);
3110 return;
3113 lines = file_lines_load(mapfile, &numlines);
3114 if (numlines == 0) {
3115 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3116 return;
3119 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3121 for( i = 0; i < numlines; i++) {
3122 char *nt_name = lines[i];
3123 char *os2_name = strchr(nt_name,'=');
3125 if (!os2_name)
3126 continue;
3128 *os2_name++ = 0;
3130 while (isspace(*nt_name))
3131 nt_name++;
3133 if (!*nt_name || strchr("#;",*nt_name))
3134 continue;
3137 int l = strlen(nt_name);
3138 while (l && isspace(nt_name[l-1])) {
3139 nt_name[l-1] = 0;
3140 l--;
3144 while (isspace(*os2_name))
3145 os2_name++;
3148 int l = strlen(os2_name);
3149 while (l && isspace(os2_name[l-1])) {
3150 os2_name[l-1] = 0;
3151 l--;
3155 if (strequal(nt_name,drivername)) {
3156 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3157 fstrcpy(last_from,drivername);
3158 fstrcpy(last_to,os2_name);
3159 fstrcpy(drivername,os2_name);
3160 file_lines_free(lines);
3161 return;
3165 file_lines_free(lines);
3168 /****************************************************************************
3169 Get a default printer info 2 struct.
3170 ****************************************************************************/
3171 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3173 int snum;
3174 NT_PRINTER_INFO_LEVEL_2 info;
3176 ZERO_STRUCT(info);
3178 snum = lp_servicenumber(sharename);
3180 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3181 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3182 get_called_name(), sharename);
3183 fstrcpy(info.sharename, sharename);
3184 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3186 /* by setting the driver name to an empty string, a local NT admin
3187 can now run the **local** APW to install a local printer driver
3188 for a Samba shared printer in 2.2. Without this, drivers **must** be
3189 installed on the Samba server for NT clients --jerry */
3190 #if 0 /* JERRY --do not uncomment-- */
3191 if (!*info.drivername)
3192 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3193 #endif
3196 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3198 pstrcpy(info.comment, "");
3199 fstrcpy(info.printprocessor, "winprint");
3200 fstrcpy(info.datatype, "RAW");
3202 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3204 info.starttime = 0; /* Minutes since 12:00am GMT */
3205 info.untiltime = 0; /* Minutes since 12:00am GMT */
3206 info.priority = 1;
3207 info.default_priority = 1;
3208 info.setuptime = (uint32)time(NULL);
3211 * I changed this as I think it is better to have a generic
3212 * DEVMODE than to crash Win2k explorer.exe --jerry
3213 * See the HP Deskjet 990c Win2k drivers for an example.
3215 * However the default devmode appears to cause problems
3216 * with the HP CLJ 8500 PCL driver. Hence the addition of
3217 * the "default devmode" parameter --jerry 22/01/2002
3220 if (lp_default_devmode(snum)) {
3221 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3222 goto fail;
3224 else {
3225 info.devmode = NULL;
3228 /* This will get the current RPC talloc context, but we should be
3229 passing this as a parameter... fixme... JRA ! */
3231 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3232 goto fail;
3234 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3235 if (! *info_ptr) {
3236 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3237 goto fail;
3240 return WERR_OK;
3242 fail:
3243 if (info.devmode)
3244 free_nt_devicemode(&info.devmode);
3245 return WERR_ACCESS_DENIED;
3248 /****************************************************************************
3249 ****************************************************************************/
3250 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3252 pstring key;
3253 NT_PRINTER_INFO_LEVEL_2 info;
3254 int len = 0;
3255 TDB_DATA kbuf, dbuf;
3256 fstring printername;
3257 char adevice[MAXDEVICENAME];
3259 ZERO_STRUCT(info);
3261 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3263 kbuf.dptr = key;
3264 kbuf.dsize = strlen(key)+1;
3266 dbuf = tdb_fetch(tdb_printers, kbuf);
3267 if (!dbuf.dptr)
3268 return get_a_printer_2_default(info_ptr, sharename);
3270 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3271 &info.attributes,
3272 &info.priority,
3273 &info.default_priority,
3274 &info.starttime,
3275 &info.untiltime,
3276 &info.status,
3277 &info.cjobs,
3278 &info.averageppm,
3279 &info.changeid,
3280 &info.c_setprinter,
3281 &info.setuptime,
3282 info.servername,
3283 info.printername,
3284 info.sharename,
3285 info.portname,
3286 info.drivername,
3287 info.comment,
3288 info.location,
3289 info.sepfile,
3290 info.printprocessor,
3291 info.datatype,
3292 info.parameters);
3294 /* Samba has to have shared raw drivers. */
3295 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3297 /* Restore the stripped strings. */
3298 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3299 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3300 info.printername);
3301 fstrcpy(info.printername, printername);
3303 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3306 * Some client drivers freak out if there is a NULL devmode
3307 * (probably the driver is not checking before accessing
3308 * the devmode pointer) --jerry
3310 * See comments in get_a_printer_2_default()
3313 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3314 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3315 printername));
3316 info.devmode = construct_nt_devicemode(printername);
3319 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3320 if (info.devmode) {
3321 fstrcpy(info.devmode->devicename, adevice);
3324 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3326 /* This will get the current RPC talloc context, but we should be
3327 passing this as a parameter... fixme... JRA ! */
3329 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3331 /* Fix for OS/2 drivers. */
3333 if (get_remote_arch() == RA_OS2)
3334 map_to_os2_driver(info.drivername);
3336 SAFE_FREE(dbuf.dptr);
3337 *info_ptr=memdup(&info, sizeof(info));
3339 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3340 sharename, info.printername, info.drivername));
3342 return WERR_OK;
3345 /****************************************************************************
3346 Debugging function, dump at level 6 the struct in the logs.
3347 ****************************************************************************/
3348 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3350 uint32 result;
3351 NT_PRINTER_INFO_LEVEL_2 *info2;
3353 DEBUG(106,("Dumping printer at level [%d]\n", level));
3355 switch (level) {
3356 case 2:
3358 if (printer.info_2 == NULL)
3359 result=5;
3360 else
3362 info2=printer.info_2;
3364 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3365 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3366 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3367 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3368 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3369 DEBUGADD(106,("status:[%d]\n", info2->status));
3370 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3371 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3372 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3373 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3374 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3376 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3377 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3378 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3379 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3380 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3381 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3382 DEBUGADD(106,("location:[%s]\n", info2->location));
3383 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3384 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3385 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3386 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3387 result=0;
3389 break;
3391 default:
3392 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3393 result=1;
3394 break;
3397 return result;
3400 /****************************************************************************
3401 Update the changeid time.
3402 This is SO NASTY as some drivers need this to change, others need it
3403 static. This value will change every second, and I must hope that this
3404 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3405 UTAH ! JRA.
3406 ****************************************************************************/
3408 static uint32 rev_changeid(void)
3410 struct timeval tv;
3412 get_process_uptime(&tv);
3414 #if 1 /* JERRY */
3415 /* Return changeid as msec since spooler restart */
3416 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3417 #else
3419 * This setting seems to work well but is too untested
3420 * to replace the above calculation. Left in for experiementation
3421 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3423 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3424 #endif
3428 * The function below are the high level ones.
3429 * only those ones must be called from the spoolss code.
3430 * JFM.
3433 /****************************************************************************
3434 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3435 ****************************************************************************/
3437 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3439 WERROR result;
3441 dump_a_printer(printer, level);
3444 * invalidate cache for all open handles to this printer.
3445 * cache for a given handle will be updated on the next
3446 * get_a_printer()
3449 invalidate_printer_hnd_cache( printer.info_2->sharename );
3451 switch (level) {
3452 case 2:
3455 * Update the changestamp. Emperical tests show that the
3456 * ChangeID is always updated,but c_setprinter is
3457 * global spooler variable (not per printer).
3460 /* ChangeID **must** be increasing over the lifetime
3461 of client's spoolss service in order for the
3462 client's cache to show updates */
3464 printer.info_2->changeid = rev_changeid();
3467 * Because one day someone will ask:
3468 * NT->NT An admin connection to a remote
3469 * printer show changes imeediately in
3470 * the properities dialog
3472 * A non-admin connection will only show the
3473 * changes after viewing the properites page
3474 * 2 times. Seems to be related to a
3475 * race condition in the client between the spooler
3476 * updating the local cache and the Explorer.exe GUI
3477 * actually displaying the properties.
3479 * This is fixed in Win2k. admin/non-admin
3480 * connections both display changes immediately.
3482 * 14/12/01 --jerry
3485 result=update_a_printer_2(printer.info_2);
3487 break;
3489 default:
3490 result=WERR_UNKNOWN_LEVEL;
3491 break;
3494 return result;
3497 /****************************************************************************
3498 Initialize printer devmode & data with previously saved driver init values.
3499 ****************************************************************************/
3501 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3503 int len = 0;
3504 pstring key;
3505 TDB_DATA kbuf, dbuf;
3506 NT_PRINTER_INFO_LEVEL_2 info;
3509 ZERO_STRUCT(info);
3512 * Delete any printer data 'values' already set. When called for driver
3513 * replace, there will generally be some, but during an add printer, there
3514 * should not be any (if there are delete them).
3517 delete_all_printer_data( info_ptr, "" );
3519 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3521 kbuf.dptr = key;
3522 kbuf.dsize = strlen(key)+1;
3524 dbuf = tdb_fetch(tdb_drivers, kbuf);
3525 if (!dbuf.dptr) {
3527 * When changing to a driver that has no init info in the tdb, remove
3528 * the previous drivers init info and leave the new on blank.
3530 free_nt_devicemode(&info_ptr->devmode);
3531 return False;
3535 * Get the saved DEVMODE..
3538 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3541 * The saved DEVMODE contains the devicename from the printer used during
3542 * the initialization save. Change it to reflect the new printer.
3545 if ( info.devmode ) {
3546 ZERO_STRUCT(info.devmode->devicename);
3547 fstrcpy(info.devmode->devicename, info_ptr->printername);
3551 * NT/2k does not change out the entire DeviceMode of a printer
3552 * when changing the driver. Only the driverextra, private, &
3553 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3555 * Later examination revealed that Windows NT/2k does reset the
3556 * the printer's device mode, bit **only** when you change a
3557 * property of the device mode such as the page orientation.
3558 * --jerry
3562 /* Bind the saved DEVMODE to the new the printer */
3564 free_nt_devicemode(&info_ptr->devmode);
3565 info_ptr->devmode = info.devmode;
3567 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3568 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3570 /* Add the printer data 'values' to the new printer */
3572 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3575 SAFE_FREE(dbuf.dptr);
3577 return True;
3580 /****************************************************************************
3581 Initialize printer devmode & data with previously saved driver init values.
3582 When a printer is created using AddPrinter, the drivername bound to the
3583 printer is used to lookup previously saved driver initialization info, which
3584 is bound to the new printer.
3585 ****************************************************************************/
3587 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3589 BOOL result = False;
3591 switch (level) {
3592 case 2:
3593 result = set_driver_init_2(printer->info_2);
3594 break;
3596 default:
3597 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3598 level));
3599 break;
3602 return result;
3605 /****************************************************************************
3606 Delete driver init data stored for a specified driver
3607 ****************************************************************************/
3609 BOOL del_driver_init(char *drivername)
3611 pstring key;
3612 TDB_DATA kbuf;
3614 if (!drivername || !*drivername) {
3615 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3616 return False;
3619 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3621 kbuf.dptr = key;
3622 kbuf.dsize = strlen(key)+1;
3624 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3626 return (tdb_delete(tdb_drivers, kbuf) == 0);
3629 /****************************************************************************
3630 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3631 in the tdb. Note: this is different from the driver entry and the printer
3632 entry. There should be a single driver init entry for each driver regardless
3633 of whether it was installed from NT or 2K. Technically, they should be
3634 different, but they work out to the same struct.
3635 ****************************************************************************/
3637 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3639 pstring key;
3640 char *buf;
3641 int buflen, len, ret;
3642 TDB_DATA kbuf, dbuf;
3644 buf = NULL;
3645 buflen = 0;
3647 again:
3648 len = 0;
3649 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3651 len += pack_values( &info->data, buf+len, buflen-len );
3653 if (buflen != len) {
3654 char *tb;
3656 tb = (char *)Realloc(buf, len);
3657 if (!tb) {
3658 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3659 ret = -1;
3660 goto done;
3662 else
3663 buf = tb;
3664 buflen = len;
3665 goto again;
3668 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3670 kbuf.dptr = key;
3671 kbuf.dsize = strlen(key)+1;
3672 dbuf.dptr = buf;
3673 dbuf.dsize = len;
3675 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3677 done:
3678 if (ret == -1)
3679 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3681 SAFE_FREE(buf);
3683 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3684 info->sharename, info->drivername));
3686 return ret;
3689 /****************************************************************************
3690 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3691 ****************************************************************************/
3693 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3695 uint32 result;
3697 dump_a_printer(printer, level);
3699 switch (level) {
3700 case 2:
3701 result = update_driver_init_2(printer.info_2);
3702 break;
3703 default:
3704 result = 1;
3705 break;
3708 return result;
3711 /****************************************************************************
3712 Convert the printer data value, a REG_BINARY array, into an initialization
3713 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3714 got to keep the endians happy :).
3715 ****************************************************************************/
3717 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3719 BOOL result = False;
3720 prs_struct ps;
3721 DEVICEMODE devmode;
3723 ZERO_STRUCT(devmode);
3725 prs_init(&ps, 0, ctx, UNMARSHALL);
3726 ps.data_p = (char *)data;
3727 ps.buffer_size = data_len;
3729 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3730 result = convert_devicemode("", &devmode, &nt_devmode);
3731 else
3732 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3734 return result;
3737 /****************************************************************************
3738 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3740 1. Use the driver's config DLL to this UNC printername and:
3741 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3742 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3743 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3745 The last step triggers saving the "driver initialization" information for
3746 this printer into the tdb. Later, new printers that use this driver will
3747 have this initialization information bound to them. This simulates the
3748 driver initialization, as if it had run on the Samba server (as it would
3749 have done on NT).
3751 The Win32 client side code requirement sucks! But until we can run arbitrary
3752 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3754 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3755 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3756 about it and you will realize why. JRR 010720
3757 ****************************************************************************/
3759 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3761 WERROR status = WERR_OK;
3762 TALLOC_CTX *ctx = NULL;
3763 NT_DEVICEMODE *nt_devmode = NULL;
3764 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3767 * When the DEVMODE is already set on the printer, don't try to unpack it.
3769 DEBUG(8,("save_driver_init_2: Enter...\n"));
3771 if ( !printer->info_2->devmode && data_len ) {
3773 * Set devmode on printer info, so entire printer initialization can be
3774 * saved to tdb.
3777 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3778 return WERR_NOMEM;
3780 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3781 status = WERR_NOMEM;
3782 goto done;
3785 ZERO_STRUCTP(nt_devmode);
3788 * The DEVMODE is held in the 'data' component of the param in raw binary.
3789 * Convert it to to a devmode structure
3791 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3792 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3793 status = WERR_INVALID_PARAM;
3794 goto done;
3797 printer->info_2->devmode = nt_devmode;
3801 * Pack up and add (or update) the DEVMODE and any current printer data to
3802 * a 'driver init' element in the tdb
3806 if ( update_driver_init(*printer, 2) != 0 ) {
3807 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3808 status = WERR_NOMEM;
3809 goto done;
3813 * If driver initialization info was successfully saved, set the current
3814 * printer to match it. This allows initialization of the current printer
3815 * as well as the driver.
3817 status = mod_a_printer(*printer, 2);
3818 if (!W_ERROR_IS_OK(status)) {
3819 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3820 printer->info_2->printername));
3823 done:
3824 talloc_destroy(ctx);
3825 free_nt_devicemode( &nt_devmode );
3827 printer->info_2->devmode = tmp_devmode;
3829 return status;
3832 /****************************************************************************
3833 Update the driver init info (DEVMODE and specifics) for a printer
3834 ****************************************************************************/
3836 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3838 WERROR status = WERR_OK;
3840 switch (level) {
3841 case 2:
3842 status = save_driver_init_2( printer, data, data_len );
3843 break;
3844 default:
3845 status = WERR_UNKNOWN_LEVEL;
3846 break;
3849 return status;
3852 /****************************************************************************
3853 Deep copy a NT_PRINTER_DATA
3854 ****************************************************************************/
3856 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3858 int i, j, num_vals, new_key_index;
3859 REGVAL_CTR *src_key, *dst_key;
3861 if ( !dst || !src )
3862 return NT_STATUS_NO_MEMORY;
3864 for ( i=0; i<src->num_keys; i++ ) {
3866 /* create a new instance of the printerkey in the destination
3867 printer_data object */
3869 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3870 dst_key = &dst->keys[new_key_index].values;
3872 src_key = &src->keys[i].values;
3873 num_vals = regval_ctr_numvals( src_key );
3875 /* dup the printer entire printer key */
3877 for ( j=0; j<num_vals; j++ ) {
3878 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3882 return NT_STATUS_OK;
3885 /****************************************************************************
3886 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3887 Caller must free.
3888 ****************************************************************************/
3890 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3892 NT_PRINTER_INFO_LEVEL_2 *copy;
3894 if ( !printer )
3895 return NULL;
3897 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3898 return NULL;
3900 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3902 /* malloc()'d members copied here */
3904 copy->devmode = dup_nt_devicemode( printer->devmode );
3906 ZERO_STRUCT( copy->data );
3907 copy_printer_data( &copy->data, &printer->data );
3909 /* this is talloc()'d; very ugly that we have a structure that
3910 is half malloc()'d and half talloc()'d but that is the way
3911 that the PRINTER_INFO stuff is written right now. --jerry */
3913 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3915 return copy;
3918 /****************************************************************************
3919 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3920 ****************************************************************************/
3922 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3923 const char *sharename)
3925 WERROR result;
3926 NT_PRINTER_INFO_LEVEL *printer = NULL;
3928 *pp_printer = NULL;
3930 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3932 switch (level) {
3933 case 2:
3934 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3935 DEBUG(0,("get_a_printer: malloc fail.\n"));
3936 return WERR_NOMEM;
3938 ZERO_STRUCTP(printer);
3941 * check for cache first. A Printer handle cannot changed
3942 * to another printer object so we only check that the printer
3943 * is actually for a printer and that the printer_info pointer
3944 * is valid
3946 if ( print_hnd
3947 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
3948 && print_hnd->printer_info )
3950 if ( !(printer->info_2 = dup_printer_2(print_hnd->ctx, print_hnd->printer_info->info_2)) ) {
3951 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
3953 SAFE_FREE(printer);
3954 return WERR_NOMEM;
3957 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
3959 *pp_printer = printer;
3960 result = WERR_OK;
3962 break;
3965 /* no cache for this handle; see if we can match one from another handle */
3967 if ( print_hnd )
3968 result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename);
3970 /* fail to disk if we don't have it with any open handle */
3972 if ( !print_hnd || !W_ERROR_IS_OK(result) )
3973 result = get_a_printer_2(&printer->info_2, sharename);
3975 /* we have a new printer now. Save it with this handle */
3977 if ( W_ERROR_IS_OK(result) ) {
3978 dump_a_printer(*printer, level);
3980 /* save a copy in cache */
3981 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
3982 if ( !print_hnd->printer_info )
3983 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
3985 if ( print_hnd->printer_info ) {
3986 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
3988 /* don't fail the lookup just because the cache update failed */
3989 if ( !print_hnd->printer_info->info_2 )
3990 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
3993 *pp_printer = printer;
3995 else
3996 SAFE_FREE(printer);
3998 break;
4000 default:
4001 result=WERR_UNKNOWN_LEVEL;
4002 break;
4005 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4007 return result;
4010 /****************************************************************************
4011 Deletes a NT_PRINTER_INFO_LEVEL struct.
4012 ****************************************************************************/
4014 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4016 uint32 result;
4017 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4019 DEBUG(104,("freeing a printer at level [%d]\n", level));
4021 if (printer == NULL)
4022 return 0;
4024 switch (level) {
4025 case 2:
4026 if (printer->info_2 != NULL) {
4027 free_nt_printer_info_level_2(&printer->info_2);
4028 result=0;
4029 } else
4030 result=4;
4031 break;
4033 default:
4034 result=1;
4035 break;
4038 SAFE_FREE(*pp_printer);
4039 return result;
4042 /****************************************************************************
4043 ****************************************************************************/
4044 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4046 uint32 result;
4047 DEBUG(104,("adding a printer at level [%d]\n", level));
4048 dump_a_printer_driver(driver, level);
4050 switch (level) {
4051 case 3:
4052 result=add_a_printer_driver_3(driver.info_3);
4053 break;
4055 case 6:
4056 result=add_a_printer_driver_6(driver.info_6);
4057 break;
4059 default:
4060 result=1;
4061 break;
4064 return result;
4066 /****************************************************************************
4067 ****************************************************************************/
4069 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4070 fstring drivername, const char *architecture, uint32 version)
4072 WERROR result;
4074 switch (level) {
4075 case 3:
4076 /* Sometime we just want any version of the driver */
4078 if ( version == DRIVER_ANY_VERSION ) {
4079 /* look for Win2k first and then for NT4 */
4080 result = get_a_printer_driver_3(&driver->info_3, drivername,
4081 architecture, 3);
4083 if ( !W_ERROR_IS_OK(result) ) {
4084 result = get_a_printer_driver_3( &driver->info_3,
4085 drivername, architecture, 2 );
4087 } else {
4088 result = get_a_printer_driver_3(&driver->info_3, drivername,
4089 architecture, version);
4091 break;
4093 default:
4094 result=W_ERROR(1);
4095 break;
4098 if (W_ERROR_IS_OK(result))
4099 dump_a_printer_driver(*driver, level);
4101 return result;
4104 /****************************************************************************
4105 ****************************************************************************/
4106 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4108 uint32 result;
4110 switch (level) {
4111 case 3:
4113 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4114 if (driver.info_3 != NULL)
4116 info3=driver.info_3;
4117 SAFE_FREE(info3->dependentfiles);
4118 ZERO_STRUCTP(info3);
4119 SAFE_FREE(info3);
4120 result=0;
4121 } else {
4122 result=4;
4124 break;
4126 case 6:
4128 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4129 if (driver.info_6 != NULL) {
4130 info6=driver.info_6;
4131 SAFE_FREE(info6->dependentfiles);
4132 SAFE_FREE(info6->previousnames);
4133 ZERO_STRUCTP(info6);
4134 SAFE_FREE(info6);
4135 result=0;
4136 } else {
4137 result=4;
4139 break;
4141 default:
4142 result=1;
4143 break;
4145 return result;
4149 /****************************************************************************
4150 Determine whether or not a particular driver is currently assigned
4151 to a printer
4152 ****************************************************************************/
4154 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4156 int snum;
4157 int n_services = lp_numservices();
4158 NT_PRINTER_INFO_LEVEL *printer = NULL;
4160 if ( !info_3 )
4161 return False;
4163 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4165 /* loop through the printers.tdb and check for the drivername */
4167 for (snum=0; snum<n_services; snum++) {
4168 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4169 continue;
4171 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4172 continue;
4174 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4175 free_a_printer( &printer, 2 );
4176 return True;
4179 free_a_printer( &printer, 2 );
4182 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4184 /* report that the driver is not in use by default */
4186 return False;
4190 /**********************************************************************
4191 Check to see if a ogiven file is in use by *info
4192 *********************************************************************/
4194 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4196 int i = 0;
4198 if ( !info )
4199 return False;
4201 if ( strequal(file, info->driverpath) )
4202 return True;
4204 if ( strequal(file, info->datafile) )
4205 return True;
4207 if ( strequal(file, info->configfile) )
4208 return True;
4210 if ( strequal(file, info->helpfile) )
4211 return True;
4213 /* see of there are any dependent files to examine */
4215 if ( !info->dependentfiles )
4216 return False;
4218 while ( *info->dependentfiles[i] ) {
4219 if ( strequal(file, info->dependentfiles[i]) )
4220 return True;
4221 i++;
4224 return False;
4228 /**********************************************************************
4229 Utility function to remove the dependent file pointed to by the
4230 input parameter from the list
4231 *********************************************************************/
4233 static void trim_dependent_file( fstring files[], int idx )
4236 /* bump everything down a slot */
4238 while( *files[idx+1] ) {
4239 fstrcpy( files[idx], files[idx+1] );
4240 idx++;
4243 *files[idx] = '\0';
4245 return;
4248 /**********************************************************************
4249 Check if any of the files used by src are also used by drv
4250 *********************************************************************/
4252 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4253 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4255 BOOL in_use = False;
4256 int i = 0;
4258 if ( !src || !drv )
4259 return False;
4261 /* check each file. Remove it from the src structure if it overlaps */
4263 if ( drv_file_in_use(src->driverpath, drv) ) {
4264 in_use = True;
4265 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4266 fstrcpy( src->driverpath, "" );
4269 if ( drv_file_in_use(src->datafile, drv) ) {
4270 in_use = True;
4271 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4272 fstrcpy( src->datafile, "" );
4275 if ( drv_file_in_use(src->configfile, drv) ) {
4276 in_use = True;
4277 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4278 fstrcpy( src->configfile, "" );
4281 if ( drv_file_in_use(src->helpfile, drv) ) {
4282 in_use = True;
4283 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4284 fstrcpy( src->helpfile, "" );
4287 /* are there any dependentfiles to examine? */
4289 if ( !src->dependentfiles )
4290 return in_use;
4292 while ( *src->dependentfiles[i] ) {
4293 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4294 in_use = True;
4295 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4296 trim_dependent_file( src->dependentfiles, i );
4297 } else
4298 i++;
4301 return in_use;
4304 /****************************************************************************
4305 Determine whether or not a particular driver files are currently being
4306 used by any other driver.
4308 Return value is True if any files were in use by other drivers
4309 and False otherwise.
4311 Upon return, *info has been modified to only contain the driver files
4312 which are not in use
4313 ****************************************************************************/
4315 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4317 int i;
4318 int ndrivers;
4319 uint32 version;
4320 fstring *list = NULL;
4321 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4323 if ( !info )
4324 return False;
4326 version = info->cversion;
4328 /* loop over all driver versions */
4330 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4332 /* get the list of drivers */
4334 list = NULL;
4335 ndrivers = get_ntdrivers(&list, info->environment, version);
4337 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4338 ndrivers, info->environment, version));
4340 /* check each driver for overlap in files */
4342 for (i=0; i<ndrivers; i++) {
4343 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4345 ZERO_STRUCT(driver);
4347 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4348 SAFE_FREE(list);
4349 return True;
4352 /* check if d2 uses any files from d1 */
4353 /* only if this is a different driver than the one being deleted */
4355 if ( !strequal(info->name, driver.info_3->name) ) {
4356 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4357 free_a_printer_driver(driver, 3);
4358 SAFE_FREE( list );
4359 return True;
4363 free_a_printer_driver(driver, 3);
4366 SAFE_FREE(list);
4368 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4370 driver.info_3 = info;
4372 if ( DEBUGLEVEL >= 20 )
4373 dump_a_printer_driver( driver, 3 );
4375 return False;
4378 /****************************************************************************
4379 Actually delete the driver files. Make sure that
4380 printer_driver_files_in_use() return False before calling
4381 this.
4382 ****************************************************************************/
4384 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4386 int i = 0;
4387 char *s;
4388 connection_struct *conn;
4389 DATA_BLOB null_pw;
4390 NTSTATUS nt_status;
4391 fstring res_type;
4393 if ( !info_3 )
4394 return False;
4396 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4399 * Connect to the print$ share under the same account as the
4400 * user connected to the rpc pipe. Note we must be root to
4401 * do this.
4404 null_pw = data_blob( NULL, 0 );
4405 fstrcpy(res_type, "A:");
4406 become_root();
4407 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4408 unbecome_root();
4410 if ( !conn ) {
4411 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4412 return False;
4415 /* Save who we are - we are temporarily becoming the connection user. */
4417 if ( !become_user(conn, conn->vuid) ) {
4418 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4419 return False;
4422 /* now delete the files; must strip the '\print$' string from
4423 fron of path */
4425 if ( *info_3->driverpath ) {
4426 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4427 DEBUG(10,("deleting driverfile [%s]\n", s));
4428 unlink_internals(conn, 0, s);
4432 if ( *info_3->configfile ) {
4433 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4434 DEBUG(10,("deleting configfile [%s]\n", s));
4435 unlink_internals(conn, 0, s);
4439 if ( *info_3->datafile ) {
4440 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4441 DEBUG(10,("deleting datafile [%s]\n", s));
4442 unlink_internals(conn, 0, s);
4446 if ( *info_3->helpfile ) {
4447 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4448 DEBUG(10,("deleting helpfile [%s]\n", s));
4449 unlink_internals(conn, 0, s);
4453 /* check if we are done removing files */
4455 if ( info_3->dependentfiles ) {
4456 while ( *info_3->dependentfiles[i] ) {
4457 char *file;
4459 /* bypass the "\print$" portion of the path */
4461 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4462 DEBUG(10,("deleting dependent file [%s]\n", file));
4463 unlink_internals(conn, 0, file );
4466 i++;
4470 unbecome_user();
4472 return True;
4475 /****************************************************************************
4476 Remove a printer driver from the TDB. This assumes that the the driver was
4477 previously looked up.
4478 ***************************************************************************/
4480 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4481 uint32 version, BOOL delete_files )
4483 pstring key;
4484 const char *arch;
4485 TDB_DATA kbuf, dbuf;
4486 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4488 /* delete the tdb data first */
4490 arch = get_short_archi(info_3->environment);
4491 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4492 arch, version, info_3->name);
4494 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4495 key, delete_files ? "TRUE" : "FALSE" ));
4497 ctr.info_3 = info_3;
4498 dump_a_printer_driver( ctr, 3 );
4500 kbuf.dptr=key;
4501 kbuf.dsize=strlen(key)+1;
4503 /* check if the driver actually exists for this environment */
4505 dbuf = tdb_fetch( tdb_drivers, kbuf );
4506 if ( !dbuf.dptr ) {
4507 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4508 return WERR_UNKNOWN_PRINTER_DRIVER;
4511 SAFE_FREE( dbuf.dptr );
4513 /* ok... the driver exists so the delete should return success */
4515 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4516 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4517 return WERR_ACCESS_DENIED;
4521 * now delete any associated files if delete_files == True
4522 * even if this part failes, we return succes because the
4523 * driver doesn not exist any more
4526 if ( delete_files )
4527 delete_driver_files( info_3, user );
4530 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4532 return WERR_OK;
4535 /****************************************************************************
4536 Store a security desc for a printer.
4537 ****************************************************************************/
4539 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4541 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4542 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4543 prs_struct ps;
4544 TALLOC_CTX *mem_ctx = NULL;
4545 fstring key;
4546 WERROR status;
4548 mem_ctx = talloc_init("nt_printing_setsec");
4549 if (mem_ctx == NULL)
4550 return WERR_NOMEM;
4552 /* The old owner and group sids of the security descriptor are not
4553 present when new ACEs are added or removed by changing printer
4554 permissions through NT. If they are NULL in the new security
4555 descriptor then copy them over from the old one. */
4557 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4558 DOM_SID *owner_sid, *group_sid;
4559 SEC_ACL *dacl, *sacl;
4560 SEC_DESC *psd = NULL;
4561 size_t size;
4563 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4565 /* Pick out correct owner and group sids */
4567 owner_sid = secdesc_ctr->sec->owner_sid ?
4568 secdesc_ctr->sec->owner_sid :
4569 old_secdesc_ctr->sec->owner_sid;
4571 group_sid = secdesc_ctr->sec->grp_sid ?
4572 secdesc_ctr->sec->grp_sid :
4573 old_secdesc_ctr->sec->grp_sid;
4575 dacl = secdesc_ctr->sec->dacl ?
4576 secdesc_ctr->sec->dacl :
4577 old_secdesc_ctr->sec->dacl;
4579 sacl = secdesc_ctr->sec->sacl ?
4580 secdesc_ctr->sec->sacl :
4581 old_secdesc_ctr->sec->sacl;
4583 /* Make a deep copy of the security descriptor */
4585 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4586 owner_sid, group_sid,
4587 sacl,
4588 dacl,
4589 &size);
4591 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4594 if (!new_secdesc_ctr) {
4595 new_secdesc_ctr = secdesc_ctr;
4598 /* Store the security descriptor in a tdb */
4600 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4601 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4603 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4604 &ps, 1)) {
4605 status = WERR_BADFUNC;
4606 goto out;
4609 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4611 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4612 status = WERR_OK;
4613 } else {
4614 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4615 status = WERR_BADFUNC;
4618 /* Free malloc'ed memory */
4620 out:
4622 prs_mem_free(&ps);
4623 if (mem_ctx)
4624 talloc_destroy(mem_ctx);
4625 return status;
4628 /****************************************************************************
4629 Construct a default security descriptor buffer for a printer.
4630 ****************************************************************************/
4632 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4634 SEC_ACE ace[3];
4635 SEC_ACCESS sa;
4636 SEC_ACL *psa = NULL;
4637 SEC_DESC_BUF *sdb = NULL;
4638 SEC_DESC *psd = NULL;
4639 DOM_SID owner_sid;
4640 size_t sd_size;
4642 /* Create an ACE where Everyone is allowed to print */
4644 init_sec_access(&sa, PRINTER_ACE_PRINT);
4645 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4646 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4648 /* Make the security descriptor owned by the Administrators group
4649 on the PDC of the domain. */
4651 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4652 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4653 } else {
4655 /* Backup plan - make printer owned by admins.
4656 This should emulate a lanman printer as security
4657 settings can't be changed. */
4659 sid_copy(&owner_sid, get_global_sam_sid());
4660 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4663 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4664 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4665 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4666 SEC_ACE_FLAG_INHERIT_ONLY);
4668 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4669 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4670 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4672 /* The ACL revision number in rpc_secdesc.h differs from the one
4673 created by NT when setting ACE entries in printer
4674 descriptors. NT4 complains about the property being edited by a
4675 NT5 machine. */
4677 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4678 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4679 &owner_sid, NULL,
4680 NULL, psa, &sd_size);
4683 if (!psd) {
4684 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4685 return NULL;
4688 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4690 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4691 (unsigned int)sd_size));
4693 return sdb;
4696 /****************************************************************************
4697 Get a security desc for a printer.
4698 ****************************************************************************/
4700 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4702 prs_struct ps;
4703 fstring key;
4704 char *temp;
4706 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4707 printername = temp + 1;
4710 /* Fetch security descriptor from tdb */
4712 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4714 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4715 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4717 DEBUG(4,("using default secdesc for %s\n", printername));
4719 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4720 return False;
4723 /* Save default security descriptor for later */
4725 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4726 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4728 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4729 tdb_prs_store(tdb_printers, key, &ps);
4731 prs_mem_free(&ps);
4733 return True;
4736 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4737 this security descriptor has been created when winbindd was
4738 down. Take ownership of security descriptor. */
4740 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4741 DOM_SID owner_sid;
4743 /* Change sd owner to workgroup administrator */
4745 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4746 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4747 SEC_DESC *psd = NULL;
4748 size_t size;
4750 /* Create new sd */
4752 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4754 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4755 &owner_sid,
4756 (*secdesc_ctr)->sec->grp_sid,
4757 (*secdesc_ctr)->sec->sacl,
4758 (*secdesc_ctr)->sec->dacl,
4759 &size);
4761 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4763 /* Swap with other one */
4765 *secdesc_ctr = new_secdesc_ctr;
4767 /* Set it */
4769 nt_printing_setsec(printername, *secdesc_ctr);
4773 if (DEBUGLEVEL >= 10) {
4774 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4775 int i;
4777 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4778 printername, the_acl->num_aces));
4780 for (i = 0; i < the_acl->num_aces; i++) {
4781 fstring sid_str;
4783 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4785 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4786 the_acl->ace[i].type, the_acl->ace[i].flags,
4787 the_acl->ace[i].info.mask));
4791 prs_mem_free(&ps);
4792 return True;
4795 /* error code:
4796 0: everything OK
4797 1: level not implemented
4798 2: file doesn't exist
4799 3: can't allocate memory
4800 4: can't free memory
4801 5: non existant struct
4805 A printer and a printer driver are 2 different things.
4806 NT manages them separatelly, Samba does the same.
4807 Why ? Simply because it's easier and it makes sense !
4809 Now explanation: You have 3 printers behind your samba server,
4810 2 of them are the same make and model (laser A and B). But laser B
4811 has an 3000 sheet feeder and laser A doesn't such an option.
4812 Your third printer is an old dot-matrix model for the accounting :-).
4814 If the /usr/local/samba/lib directory (default dir), you will have
4815 5 files to describe all of this.
4817 3 files for the printers (1 by printer):
4818 NTprinter_laser A
4819 NTprinter_laser B
4820 NTprinter_accounting
4821 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4822 NTdriver_printer model X
4823 NTdriver_printer model Y
4825 jfm: I should use this comment for the text file to explain
4826 same thing for the forms BTW.
4827 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4831 /* Convert generic access rights to printer object specific access rights.
4832 It turns out that NT4 security descriptors use generic access rights and
4833 NT5 the object specific ones. */
4835 void map_printer_permissions(SEC_DESC *sd)
4837 int i;
4839 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4840 se_map_generic(&sd->dacl->ace[i].info.mask,
4841 &printer_generic_mapping);
4845 /****************************************************************************
4846 Check a user has permissions to perform the given operation. We use the
4847 permission constants defined in include/rpc_spoolss.h to check the various
4848 actions we perform when checking printer access.
4850 PRINTER_ACCESS_ADMINISTER:
4851 print_queue_pause, print_queue_resume, update_printer_sec,
4852 update_printer, spoolss_addprinterex_level_2,
4853 _spoolss_setprinterdata
4855 PRINTER_ACCESS_USE:
4856 print_job_start
4858 JOB_ACCESS_ADMINISTER:
4859 print_job_delete, print_job_pause, print_job_resume,
4860 print_queue_purge
4862 ****************************************************************************/
4863 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4865 SEC_DESC_BUF *secdesc = NULL;
4866 uint32 access_granted;
4867 NTSTATUS status;
4868 BOOL result;
4869 const char *pname;
4870 TALLOC_CTX *mem_ctx = NULL;
4871 extern struct current_user current_user;
4873 /* If user is NULL then use the current_user structure */
4875 if (!user)
4876 user = &current_user;
4878 /* Always allow root or printer admins to do anything */
4880 if (user->uid == 0 ||
4881 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4882 return True;
4885 /* Get printer name */
4887 pname = PRINTERNAME(snum);
4889 if (!pname || !*pname) {
4890 errno = EACCES;
4891 return False;
4894 /* Get printer security descriptor */
4896 if(!(mem_ctx = talloc_init("print_access_check"))) {
4897 errno = ENOMEM;
4898 return False;
4901 nt_printing_getsec(mem_ctx, pname, &secdesc);
4903 if (access_type == JOB_ACCESS_ADMINISTER) {
4904 SEC_DESC_BUF *parent_secdesc = secdesc;
4906 /* Create a child security descriptor to check permissions
4907 against. This is because print jobs are child objects
4908 objects of a printer. */
4910 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4912 /* Now this is the bit that really confuses me. The access
4913 type needs to be changed from JOB_ACCESS_ADMINISTER to
4914 PRINTER_ACCESS_ADMINISTER for this to work. Something
4915 to do with the child (job) object becoming like a
4916 printer?? -tpot */
4918 access_type = PRINTER_ACCESS_ADMINISTER;
4921 /* Check access */
4923 map_printer_permissions(secdesc->sec);
4925 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4926 &access_granted, &status);
4928 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4930 talloc_destroy(mem_ctx);
4932 if (!result)
4933 errno = EACCES;
4935 return result;
4938 /****************************************************************************
4939 Check the time parameters allow a print operation.
4940 *****************************************************************************/
4942 BOOL print_time_access_check(int snum)
4944 NT_PRINTER_INFO_LEVEL *printer = NULL;
4945 BOOL ok = False;
4946 time_t now = time(NULL);
4947 struct tm *t;
4948 uint32 mins;
4950 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
4951 return False;
4953 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4954 ok = True;
4956 t = gmtime(&now);
4957 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4959 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4960 ok = True;
4962 free_a_printer(&printer, 2);
4964 if (!ok)
4965 errno = EACCES;
4967 return ok;