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.
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 = {
53 STANDARD_MAPPING printer_std_mapping = {
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
69 STANDARD_MAPPING printserver_std_mapping = {
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}
202 const char *long_archi;
203 const char *short_archi;
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 },
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)));
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)));
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)));
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)));
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)));
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)));
276 SAFE_FREE(dbuf.dptr);
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())
295 tdb_close(tdb_drivers);
296 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
298 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
299 lock_path("ntdrivers.tdb"), strerror(errno) ));
304 tdb_close(tdb_printers);
305 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
307 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
308 lock_path("ntprinters.tdb"), strerror(errno) ));
313 tdb_close(tdb_forms);
314 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
316 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
317 lock_path("ntforms.tdb"), strerror(errno) ));
321 local_pid = sys_getpid();
323 /* handle a Samba upgrade */
324 tdb_lock_bystring(tdb_drivers, vstring, 0);
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())
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 * register callback to handle invalidating the printer cache
368 * between smbd processes.
371 message_register( MSG_PRINTER_MOD, receive_printer_mod_msg);
373 /* of course, none of the message callbacks matter if you don't
374 tell messages.c that you interested in receiving PRINT_GENERAL
375 msgs. This is done in claim_connection() */
381 /*******************************************************************
382 Function to allow filename parsing "the old way".
383 ********************************************************************/
385 static BOOL driver_unix_convert(char *name,connection_struct *conn,
386 char *saved_last_component, BOOL *bad_path, SMB_STRUCT_STAT *pst)
389 unix_clean_name(name);
390 trim_string(name,"/","/");
391 return unix_convert(name, conn, saved_last_component, bad_path, pst);
394 /*******************************************************************
395 tdb traversal function for counting printers.
396 ********************************************************************/
398 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
399 TDB_DATA data, void *context)
401 int *printer_count = (int*)context;
403 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
405 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
411 /*******************************************************************
412 Update the spooler global c_setprinter. This variable is initialized
413 when the parent smbd starts with the number of existing printers. It
414 is monotonically increased by the current number of printers *after*
415 each add or delete printer RPC. Only Microsoft knows why... JRR020119
416 ********************************************************************/
418 uint32 update_c_setprinter(BOOL initialize)
421 int32 printer_count = 0;
423 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER, 0);
425 /* Traverse the tdb, counting the printers */
426 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
428 /* If initializing, set c_setprinter to current printers count
429 * otherwise, bump it by the current printer count
432 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
434 c_setprinter = printer_count;
436 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
437 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
439 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
441 return (uint32)c_setprinter;
444 /*******************************************************************
445 Get the spooler global c_setprinter, accounting for initialization.
446 ********************************************************************/
448 uint32 get_c_setprinter(void)
450 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
452 if (c_setprinter == (int32)-1)
453 c_setprinter = update_c_setprinter(True);
455 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
457 return (uint32)c_setprinter;
460 /****************************************************************************
461 Get builtin form struct list.
462 ****************************************************************************/
464 int get_builtin_ntforms(nt_forms_struct **list)
466 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
467 return sizeof(default_forms) / sizeof(default_forms[0]);
470 /****************************************************************************
471 get a builtin form struct
472 ****************************************************************************/
474 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
478 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
479 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
480 count = sizeof(default_forms) / sizeof(default_forms[0]);
481 for (i=0;i<count;i++) {
482 if (strequal(form_name,default_forms[i].name)) {
483 DEBUGADD(6,("Found builtin form %s \n", form_name));
484 memcpy(form,&default_forms[i],sizeof(*form));
492 /****************************************************************************
493 get a form struct list
494 ****************************************************************************/
495 int get_ntforms(nt_forms_struct **list)
497 TDB_DATA kbuf, newkey, dbuf;
499 nt_forms_struct form;
504 for (kbuf = tdb_firstkey(tdb_forms);
506 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
508 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
511 dbuf = tdb_fetch(tdb_forms, kbuf);
515 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
516 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
517 &i, &form.flag, &form.width, &form.length, &form.left,
518 &form.top, &form.right, &form.bottom);
519 SAFE_FREE(dbuf.dptr);
520 if (ret != dbuf.dsize)
523 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
525 DEBUG(0,("get_ntforms: Realloc fail.\n"));
537 /****************************************************************************
538 write a form struct list
539 ****************************************************************************/
540 int write_ntforms(nt_forms_struct **list, int number)
547 for (i=0;i<number;i++) {
548 /* save index, so list is rebuilt in correct order */
549 len = tdb_pack(buf, sizeof(buf), "dddddddd",
550 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
551 (*list)[i].left, (*list)[i].top, (*list)[i].right,
553 if (len > sizeof(buf)) break;
554 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
555 kbuf.dsize = strlen(key)+1;
559 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
565 /****************************************************************************
566 add a form struct at the end of the list
567 ****************************************************************************/
568 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
576 * NT tries to add forms even when
577 * they are already in the base
578 * only update the values if already present
583 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
584 for (n=0; n<*count; n++) {
585 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
586 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
593 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
594 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
598 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
602 (*list)[n].flag=form->flags;
603 (*list)[n].width=form->size_x;
604 (*list)[n].length=form->size_y;
605 (*list)[n].left=form->left;
606 (*list)[n].top=form->top;
607 (*list)[n].right=form->right;
608 (*list)[n].bottom=form->bottom;
613 /****************************************************************************
614 Delete a named form struct.
615 ****************************************************************************/
617 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
626 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
628 for (n=0; n<*count; n++) {
629 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
630 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
636 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
637 *ret = WERR_INVALID_PARAM;
641 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
642 kbuf.dsize = strlen(key)+1;
644 if (tdb_delete(tdb_forms, kbuf) != 0) {
652 /****************************************************************************
653 Update a form struct.
654 ****************************************************************************/
656 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
660 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
662 DEBUG(106, ("[%s]\n", form_name));
663 for (n=0; n<count; n++) {
664 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
665 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
669 if (n==count) return;
671 (*list)[n].flag=form->flags;
672 (*list)[n].width=form->size_x;
673 (*list)[n].length=form->size_y;
674 (*list)[n].left=form->left;
675 (*list)[n].top=form->top;
676 (*list)[n].right=form->right;
677 (*list)[n].bottom=form->bottom;
680 /****************************************************************************
681 Get the nt drivers list.
682 Traverse the database and look-up the matching names.
683 ****************************************************************************/
684 int get_ntdrivers(fstring **list, const char *architecture, uint32 version)
687 const char *short_archi;
690 TDB_DATA kbuf, newkey;
692 short_archi = get_short_archi(architecture);
693 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
695 for (kbuf = tdb_firstkey(tdb_drivers);
697 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
699 if (strncmp(kbuf.dptr, key, strlen(key)) != 0)
702 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
703 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
708 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
715 /****************************************************************************
716 function to do the mapping between the long architecture name and
718 ****************************************************************************/
719 const char *get_short_archi(const char *long_archi)
723 DEBUG(107,("Getting architecture dependant directory\n"));
726 } while ( (archi_table[i].long_archi!=NULL ) &&
727 StrCaseCmp(long_archi, archi_table[i].long_archi) );
729 if (archi_table[i].long_archi==NULL) {
730 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
734 /* this might be client code - but shouldn't this be an fstrcpy etc? */
737 DEBUGADD(108,("index: [%d]\n", i));
738 DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
739 DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
741 return archi_table[i].short_archi;
744 /****************************************************************************
745 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
746 There are two case to be covered here: PE (Portable Executable) and NE (New
747 Executable) files. Both files support the same INFO structure, but PE files
748 store the signature in unicode, and NE files store it as !unicode.
749 returns -1 on error, 1 on version info found, and 0 on no version info found.
750 ****************************************************************************/
752 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
758 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
759 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
760 fname, PE_HEADER_SIZE));
764 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
765 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
766 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
767 fname, (unsigned long)byte_count));
768 goto no_version_info;
771 /* Is this really a DOS header? */
772 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
773 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
774 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
775 goto no_version_info;
778 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
779 if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
780 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
782 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
783 goto no_version_info;
786 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
787 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
788 fname, (unsigned long)byte_count));
789 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
790 goto no_version_info;
793 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
794 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
795 unsigned int num_sections;
796 unsigned int section_table_bytes;
798 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
799 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
800 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
801 /* At this point, we assume the file is in error. It still could be somthing
802 * else besides a PE file, but it unlikely at this point.
807 /* get the section table */
808 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
809 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
810 if (section_table_bytes == 0)
814 if ((buf=malloc(section_table_bytes)) == NULL) {
815 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
816 fname, section_table_bytes));
820 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
821 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %lu\n",
822 fname, (unsigned long)byte_count));
826 /* Iterate the section table looking for the resource section ".rsrc" */
827 for (i = 0; i < num_sections; i++) {
828 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
830 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
831 unsigned int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
832 unsigned int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
834 if (section_bytes == 0)
838 if ((buf=malloc(section_bytes)) == NULL) {
839 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
840 fname, section_bytes));
844 /* Seek to the start of the .rsrc section info */
845 if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
846 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
851 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
852 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %lu\n",
853 fname, (unsigned long)byte_count));
857 if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE)
860 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
861 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
862 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
863 /* Align to next long address */
864 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
866 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
867 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
868 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
870 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
871 fname, *major, *minor,
872 (*major>>16)&0xffff, *major&0xffff,
873 (*minor>>16)&0xffff, *minor&0xffff));
882 /* Version info not found, fall back to origin date/time */
883 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
887 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
888 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
889 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
890 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
891 /* At this point, we assume the file is in error. It still could be somthing
892 * else besides a NE file, but it unlikely at this point. */
896 /* Allocate a bit more space to speed up things */
898 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
899 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
900 fname, PE_HEADER_SIZE));
904 /* This is a HACK! I got tired of trying to sort through the messy
905 * 'NE' file format. If anyone wants to clean this up please have at
906 * it, but this works. 'NE' files will eventually fade away. JRR */
907 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
908 /* Cover case that should not occur in a well formed 'NE' .dll file */
909 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
911 for(i=0; i<byte_count; i++) {
912 /* Fast skip past data that can't possibly match */
913 if (buf[i] != 'V') continue;
915 /* Potential match data crosses buf boundry, move it to beginning
916 * of buf, and fill the buf with as much as it will hold. */
917 if (i>byte_count-VS_VERSION_INFO_SIZE) {
920 memcpy(buf, &buf[i], byte_count-i);
921 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
922 (byte_count-i))) < 0) {
924 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
929 byte_count = bc + (byte_count - i);
930 if (byte_count<VS_VERSION_INFO_SIZE) break;
935 /* Check that the full signature string and the magic number that
936 * follows exist (not a perfect solution, but the chances that this
937 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
938 * twice, as it is simpler to read the code. */
939 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
940 /* Compute skip alignment to next long address */
941 int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
942 sizeof(VS_SIGNATURE)) & 3;
943 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
945 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
946 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
947 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
948 fname, *major, *minor,
949 (*major>>16)&0xffff, *major&0xffff,
950 (*minor>>16)&0xffff, *minor&0xffff));
957 /* Version info not found, fall back to origin date/time */
958 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
963 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
964 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
965 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
976 /****************************************************************************
977 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
978 share one or more files. During the MS installation process files are checked
979 to insure that only a newer version of a shared file is installed over an
980 older version. There are several possibilities for this comparison. If there
981 is no previous version, the new one is newer (obviously). If either file is
982 missing the version info structure, compare the creation date (on Unix use
983 the modification date). Otherwise chose the numerically larger version number.
984 ****************************************************************************/
986 static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
988 BOOL use_version = True;
993 time_t new_create_time;
997 time_t old_create_time;
1001 files_struct *fsp = NULL;
1003 SMB_STRUCT_STAT stat_buf;
1007 ZERO_STRUCT(stat_buf);
1008 new_create_time = (time_t)0;
1009 old_create_time = (time_t)0;
1011 /* Get file version info (if available) for previous file (if it exists) */
1012 pstrcpy(filepath, old_file);
1014 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1016 fsp = open_file_shared(conn, filepath, &stat_buf,
1017 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1018 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1019 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1021 /* Old file not found, so by definition new file is in fact newer */
1022 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
1027 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
1028 if (ret == -1) goto error_exit;
1031 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1033 use_version = False;
1034 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1035 old_create_time = st.st_mtime;
1036 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1039 close_file(fsp, True);
1041 /* Get file version info (if available) for new file */
1042 pstrcpy(filepath, new_file);
1043 driver_unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1045 fsp = open_file_shared(conn, filepath, &stat_buf,
1046 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1047 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1048 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1050 /* New file not found, this shouldn't occur if the caller did its job */
1051 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1056 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1057 if (ret == -1) goto error_exit;
1060 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1062 use_version = False;
1063 if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit;
1064 new_create_time = st.st_mtime;
1065 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1068 close_file(fsp, True);
1070 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1071 /* Compare versions and choose the larger version number */
1072 if (new_major > old_major ||
1073 (new_major == old_major && new_minor > old_minor)) {
1075 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1079 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1084 /* Compare modification time/dates and choose the newest time/date */
1085 if (new_create_time > old_create_time) {
1086 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1090 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1097 close_file(fsp, True);
1101 /****************************************************************************
1102 Determine the correct cVersion associated with an architecture and driver
1103 ****************************************************************************/
1104 static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
1105 struct current_user *user, WERROR *perr)
1114 files_struct *fsp = NULL;
1117 connection_struct *conn;
1121 *perr = WERR_INVALID_PARAM;
1123 /* If architecture is Windows 95/98/ME, the version is always 0. */
1124 if (strcmp(architecture, "WIN40") == 0) {
1125 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1131 * Connect to the print$ share under the same account as the user connected
1132 * to the rpc pipe. Note we must still be root to do this.
1135 /* Null password is ok - we are already an authenticated user... */
1136 null_pw = data_blob(NULL, 0);
1137 fstrcpy(res_type, "A:");
1139 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1143 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1144 *perr = ntstatus_to_werror(nt_status);
1148 /* We are temporarily becoming the connection user. */
1149 if (!become_user(conn, user->vuid)) {
1150 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1151 *perr = WERR_ACCESS_DENIED;
1155 /* Open the driver file (Portable Executable format) and determine the
1156 * deriver the cversion. */
1157 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1159 driver_unix_convert(driverpath,conn,NULL,&bad_path,&st);
1161 fsp = open_file_shared(conn, driverpath, &st,
1162 SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
1163 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1164 FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY, &access_mode, &action);
1166 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1167 driverpath, errno));
1168 *perr = WERR_ACCESS_DENIED;
1174 int ret = get_file_version(fsp, driverpath, &major, &minor);
1175 if (ret == -1) goto error_exit;
1178 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1183 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1184 * for more details. Version in this case is not just the version of the
1185 * file, but the version in the sense of kernal mode (2) vs. user mode
1186 * (3) drivers. Other bits of the version fields are the version info.
1189 cversion = major & 0x0000ffff;
1191 case 2: /* WinNT drivers */
1192 case 3: /* Win2K drivers */
1196 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1197 driverpath, cversion));
1201 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1202 driverpath, major, minor));
1205 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1206 driverpath, cversion));
1208 close_file(fsp, True);
1209 close_cnum(conn, user->vuid);
1218 close_file(fsp, True);
1220 close_cnum(conn, user->vuid);
1225 /****************************************************************************
1226 ****************************************************************************/
1227 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1228 struct current_user *user)
1230 const char *architecture;
1236 /* clean up the driver name.
1237 * we can get .\driver.dll
1238 * or worse c:\windows\system\driver.dll !
1240 /* using an intermediate string to not have overlaping memcpy()'s */
1241 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1242 fstrcpy(new_name, p+1);
1243 fstrcpy(driver->driverpath, new_name);
1246 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1247 fstrcpy(new_name, p+1);
1248 fstrcpy(driver->datafile, new_name);
1251 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1252 fstrcpy(new_name, p+1);
1253 fstrcpy(driver->configfile, new_name);
1256 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1257 fstrcpy(new_name, p+1);
1258 fstrcpy(driver->helpfile, new_name);
1261 if (driver->dependentfiles) {
1262 for (i=0; *driver->dependentfiles[i]; i++) {
1263 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1264 fstrcpy(new_name, p+1);
1265 fstrcpy(driver->dependentfiles[i], new_name);
1270 architecture = get_short_archi(driver->environment);
1272 /* jfm:7/16/2000 the client always sends the cversion=0.
1273 * The server should check which version the driver is by reading
1274 * the PE header of driver->driverpath.
1276 * For Windows 95/98 the version is 0 (so the value sent is correct)
1277 * For Windows NT (the architecture doesn't matter)
1278 * NT 3.1: cversion=0
1279 * NT 3.5/3.51: cversion=1
1283 if ((driver->cversion = get_correct_cversion( architecture,
1284 driver->driverpath, user, &err)) == -1)
1290 /****************************************************************************
1291 ****************************************************************************/
1292 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1294 const char *architecture;
1300 /* clean up the driver name.
1301 * we can get .\driver.dll
1302 * or worse c:\windows\system\driver.dll !
1304 /* using an intermediate string to not have overlaping memcpy()'s */
1305 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1306 fstrcpy(new_name, p+1);
1307 fstrcpy(driver->driverpath, new_name);
1310 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1311 fstrcpy(new_name, p+1);
1312 fstrcpy(driver->datafile, new_name);
1315 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1316 fstrcpy(new_name, p+1);
1317 fstrcpy(driver->configfile, new_name);
1320 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1321 fstrcpy(new_name, p+1);
1322 fstrcpy(driver->helpfile, new_name);
1325 if (driver->dependentfiles) {
1326 for (i=0; *driver->dependentfiles[i]; i++) {
1327 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1328 fstrcpy(new_name, p+1);
1329 fstrcpy(driver->dependentfiles[i], new_name);
1334 architecture = get_short_archi(driver->environment);
1336 /* jfm:7/16/2000 the client always sends the cversion=0.
1337 * The server should check which version the driver is by reading
1338 * the PE header of driver->driverpath.
1340 * For Windows 95/98 the version is 0 (so the value sent is correct)
1341 * For Windows NT (the architecture doesn't matter)
1342 * NT 3.1: cversion=0
1343 * NT 3.5/3.51: cversion=1
1347 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1353 /****************************************************************************
1354 ****************************************************************************/
1355 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1356 uint32 level, struct current_user *user)
1361 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1362 driver=driver_abstract.info_3;
1363 return clean_up_driver_struct_level_3(driver, user);
1367 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1368 driver=driver_abstract.info_6;
1369 return clean_up_driver_struct_level_6(driver, user);
1372 return WERR_INVALID_PARAM;
1376 /****************************************************************************
1377 This function sucks and should be replaced. JRA.
1378 ****************************************************************************/
1380 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1382 dst->cversion = src->version;
1384 fstrcpy( dst->name, src->name);
1385 fstrcpy( dst->environment, src->environment);
1386 fstrcpy( dst->driverpath, src->driverpath);
1387 fstrcpy( dst->datafile, src->datafile);
1388 fstrcpy( dst->configfile, src->configfile);
1389 fstrcpy( dst->helpfile, src->helpfile);
1390 fstrcpy( dst->monitorname, src->monitorname);
1391 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1392 dst->dependentfiles = src->dependentfiles;
1395 #if 0 /* Debugging function */
1397 static char* ffmt(unsigned char *c){
1399 static char ffmt_str[17];
1401 for (i=0; i<16; i++) {
1402 if ((c[i] < ' ') || (c[i] > '~'))
1413 /****************************************************************************
1414 ****************************************************************************/
1415 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1416 struct current_user *user, WERROR *perr)
1418 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1419 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1420 const char *architecture;
1425 connection_struct *conn;
1435 memset(inbuf, '\0', sizeof(inbuf));
1436 memset(outbuf, '\0', sizeof(outbuf));
1440 driver=driver_abstract.info_3;
1441 else if (level==6) {
1442 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1443 driver = &converted_driver;
1445 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1449 architecture = get_short_archi(driver->environment);
1452 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1453 * Note we must be root to do this.
1456 null_pw = data_blob(NULL, 0);
1457 fstrcpy(res_type, "A:");
1459 conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
1463 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1464 *perr = ntstatus_to_werror(nt_status);
1469 * Save who we are - we are temporarily becoming the connection user.
1472 if (!become_user(conn, conn->vuid)) {
1473 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1478 * make the directories version and version\driver_name
1479 * under the architecture directory.
1481 DEBUG(5,("Creating first directory\n"));
1482 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1483 driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
1484 mkdir_internal(conn, new_dir);
1486 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1487 * listed for this driver which has already been moved, skip it (note:
1488 * drivers may list the same file name several times. Then check if the
1489 * file already exists in archi\cversion\, if so, check that the version
1490 * info (or time stamps if version info is unavailable) is newer (or the
1491 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1492 * Otherwise, delete the file.
1494 * If a file is not moved to archi\cversion\ because of an error, all the
1495 * rest of the 'unmoved' driver files are removed from archi\. If one or
1496 * more of the driver's files was already moved to archi\cversion\, it
1497 * potentially leaves the driver in a partially updated state. Version
1498 * trauma will most likely occur if an client attempts to use any printer
1499 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1500 * done is appropriate... later JRR
1503 DEBUG(5,("Moving files now !\n"));
1505 if (driver->driverpath && strlen(driver->driverpath)) {
1506 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1507 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1508 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1510 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1511 status = rename_internals(conn, new_name, old_name, 0, True);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1514 new_name, old_name));
1515 *perr = ntstatus_to_werror(status);
1516 unlink_internals(conn, 0, new_name);
1520 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1521 unlink_internals(conn, 0, new_name);
1525 if (driver->datafile && strlen(driver->datafile)) {
1526 if (!strequal(driver->datafile, driver->driverpath)) {
1527 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1528 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1529 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1531 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1532 status = rename_internals(conn, new_name, old_name, 0, True);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1535 new_name, old_name));
1536 *perr = ntstatus_to_werror(status);
1537 unlink_internals(conn, 0, new_name);
1541 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1542 unlink_internals(conn, 0, new_name);
1547 if (driver->configfile && strlen(driver->configfile)) {
1548 if (!strequal(driver->configfile, driver->driverpath) &&
1549 !strequal(driver->configfile, driver->datafile)) {
1550 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1551 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1552 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1554 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1555 status = rename_internals(conn, new_name, old_name, 0, True);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1558 new_name, old_name));
1559 *perr = ntstatus_to_werror(status);
1560 unlink_internals(conn, 0, new_name);
1564 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1565 unlink_internals(conn, 0, new_name);
1570 if (driver->helpfile && strlen(driver->helpfile)) {
1571 if (!strequal(driver->helpfile, driver->driverpath) &&
1572 !strequal(driver->helpfile, driver->datafile) &&
1573 !strequal(driver->helpfile, driver->configfile)) {
1574 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1575 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1576 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1578 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1579 status = rename_internals(conn, new_name, old_name, 0, True);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1582 new_name, old_name));
1583 *perr = ntstatus_to_werror(status);
1584 unlink_internals(conn, 0, new_name);
1588 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1589 unlink_internals(conn, 0, new_name);
1594 if (driver->dependentfiles) {
1595 for (i=0; *driver->dependentfiles[i]; i++) {
1596 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1597 !strequal(driver->dependentfiles[i], driver->datafile) &&
1598 !strequal(driver->dependentfiles[i], driver->configfile) &&
1599 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1601 for (j=0; j < i; j++) {
1602 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1607 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1608 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1609 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1611 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1612 status = rename_internals(conn, new_name, old_name, 0, True);
1613 if (!NT_STATUS_IS_OK(status)) {
1614 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1615 new_name, old_name));
1616 *perr = ntstatus_to_werror(status);
1617 unlink_internals(conn, 0, new_name);
1621 driver_unix_convert(new_name, conn, NULL, &bad_path, &st);
1622 unlink_internals(conn, 0, new_name);
1629 close_cnum(conn, user->vuid);
1632 return ver == -1 ? False : True;
1635 /****************************************************************************
1636 ****************************************************************************/
1637 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1640 const char *architecture;
1646 TDB_DATA kbuf, dbuf;
1648 architecture = get_short_archi(driver->environment);
1650 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1651 * \\server is added in the rpc server layer.
1652 * It does make sense to NOT store the server's name in the printer TDB.
1655 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1657 /* .inf files do not always list a file for each of the four standard files.
1658 * Don't prepend a path to a null filename, or client claims:
1659 * "The server on which the printer resides does not have a suitable
1660 * <printer driver name> printer driver installed. Click OK if you
1661 * wish to install the driver on your local machine."
1663 if (strlen(driver->driverpath)) {
1664 fstrcpy(temp_name, driver->driverpath);
1665 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1668 if (strlen(driver->datafile)) {
1669 fstrcpy(temp_name, driver->datafile);
1670 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1673 if (strlen(driver->configfile)) {
1674 fstrcpy(temp_name, driver->configfile);
1675 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1678 if (strlen(driver->helpfile)) {
1679 fstrcpy(temp_name, driver->helpfile);
1680 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1683 if (driver->dependentfiles) {
1684 for (i=0; *driver->dependentfiles[i]; i++) {
1685 fstrcpy(temp_name, driver->dependentfiles[i]);
1686 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1690 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1692 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1699 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1702 driver->environment,
1707 driver->monitorname,
1708 driver->defaultdatatype);
1710 if (driver->dependentfiles) {
1711 for (i=0; *driver->dependentfiles[i]; i++) {
1712 len += tdb_pack(buf+len, buflen-len, "f",
1713 driver->dependentfiles[i]);
1717 if (len != buflen) {
1720 tb = (char *)Realloc(buf, len);
1722 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1733 kbuf.dsize = strlen(key)+1;
1737 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1741 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1747 /****************************************************************************
1748 ****************************************************************************/
1749 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1751 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1754 info3.cversion = driver->version;
1755 fstrcpy(info3.name,driver->name);
1756 fstrcpy(info3.environment,driver->environment);
1757 fstrcpy(info3.driverpath,driver->driverpath);
1758 fstrcpy(info3.datafile,driver->datafile);
1759 fstrcpy(info3.configfile,driver->configfile);
1760 fstrcpy(info3.helpfile,driver->helpfile);
1761 fstrcpy(info3.monitorname,driver->monitorname);
1762 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1763 info3.dependentfiles = driver->dependentfiles;
1765 return add_a_printer_driver_3(&info3);
1769 /****************************************************************************
1770 ****************************************************************************/
1771 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
1773 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1777 fstrcpy(info.name, driver);
1778 fstrcpy(info.defaultdatatype, "RAW");
1780 fstrcpy(info.driverpath, "");
1781 fstrcpy(info.datafile, "");
1782 fstrcpy(info.configfile, "");
1783 fstrcpy(info.helpfile, "");
1785 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1788 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1789 fstrcpy(info.dependentfiles[0], "");
1791 *info_ptr = memdup(&info, sizeof(info));
1796 /****************************************************************************
1797 ****************************************************************************/
1798 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
1800 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1801 TDB_DATA kbuf, dbuf;
1802 const char *architecture;
1807 ZERO_STRUCT(driver);
1809 architecture = get_short_archi(arch);
1811 /* Windows 4.0 (i.e. win9x) should always use a version of 0 */
1813 if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 )
1816 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1818 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1821 kbuf.dsize = strlen(key)+1;
1823 dbuf = tdb_fetch(tdb_drivers, kbuf);
1825 return WERR_UNKNOWN_PRINTER_DRIVER;
1827 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1836 driver.defaultdatatype);
1839 while (len < dbuf.dsize) {
1842 tddfs = (fstring *)Realloc(driver.dependentfiles,
1843 sizeof(fstring)*(i+2));
1844 if (tddfs == NULL) {
1845 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1848 else driver.dependentfiles = tddfs;
1850 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1851 &driver.dependentfiles[i]);
1855 if (driver.dependentfiles != NULL)
1856 fstrcpy(driver.dependentfiles[i], "");
1858 SAFE_FREE(dbuf.dptr);
1860 if (len != dbuf.dsize) {
1861 SAFE_FREE(driver.dependentfiles);
1863 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1866 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1871 /****************************************************************************
1872 Debugging function, dump at level 6 the struct in the logs.
1873 ****************************************************************************/
1875 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1878 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1881 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1887 if (driver.info_3 == NULL)
1890 info3=driver.info_3;
1892 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1893 DEBUGADD(20,("name:[%s]\n", info3->name));
1894 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1895 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1896 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1897 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1898 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1899 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1900 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1902 for (i=0; info3->dependentfiles &&
1903 *info3->dependentfiles[i]; i++) {
1904 DEBUGADD(20,("dependentfile:[%s]\n",
1905 info3->dependentfiles[i]));
1912 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1920 /****************************************************************************
1921 ****************************************************************************/
1922 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1926 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1931 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1932 nt_devmode->devicename,
1933 nt_devmode->formname,
1935 nt_devmode->specversion,
1936 nt_devmode->driverversion,
1938 nt_devmode->driverextra,
1939 nt_devmode->orientation,
1940 nt_devmode->papersize,
1941 nt_devmode->paperlength,
1942 nt_devmode->paperwidth,
1945 nt_devmode->defaultsource,
1946 nt_devmode->printquality,
1949 nt_devmode->yresolution,
1950 nt_devmode->ttoption,
1951 nt_devmode->collate,
1952 nt_devmode->logpixels,
1955 nt_devmode->bitsperpel,
1956 nt_devmode->pelswidth,
1957 nt_devmode->pelsheight,
1958 nt_devmode->displayflags,
1959 nt_devmode->displayfrequency,
1960 nt_devmode->icmmethod,
1961 nt_devmode->icmintent,
1962 nt_devmode->mediatype,
1963 nt_devmode->dithertype,
1964 nt_devmode->reserved1,
1965 nt_devmode->reserved2,
1966 nt_devmode->panningwidth,
1967 nt_devmode->panningheight,
1968 nt_devmode->private);
1971 if (nt_devmode->private) {
1972 len += tdb_pack(buf+len, buflen-len, "B",
1973 nt_devmode->driverextra,
1974 nt_devmode->private);
1977 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1982 /****************************************************************************
1983 Pack all values in all printer keys
1984 ***************************************************************************/
1986 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1990 REGISTRY_VALUE *val;
1991 REGVAL_CTR *val_ctr;
1998 /* loop over all keys */
2000 for ( i=0; i<data->num_keys; i++ ) {
2001 val_ctr = &data->keys[i].values;
2002 num_values = regval_ctr_numvals( val_ctr );
2004 /* loop over all values */
2006 for ( j=0; j<num_values; j++ ) {
2007 /* pathname should be stored as <key>\<value> */
2009 val = regval_ctr_specific_value( val_ctr, j );
2010 pstrcpy( path, data->keys[i].name );
2011 pstrcat( path, "\\" );
2012 pstrcat( path, regval_name(val) );
2014 len += tdb_pack(buf+len, buflen-len, "pPdB",
2019 regval_data_p(val) );
2026 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2032 /****************************************************************************
2033 Delete a printer - this just deletes the printer info file, any open
2034 handles are not affected.
2035 ****************************************************************************/
2037 uint32 del_a_printer(char *sharename)
2042 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2045 kbuf.dsize=strlen(key)+1;
2047 tdb_delete(tdb_printers, kbuf);
2051 /****************************************************************************
2052 ****************************************************************************/
2053 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2059 TDB_DATA kbuf, dbuf;
2062 * in addprinter: no servername and the printer is the name
2063 * in setprinter: servername is \\server
2064 * and printer is \\server\\printer
2066 * Samba manages only local printers.
2067 * we currently don't support things like i
2068 * path=\\other_server\printer
2070 * We only store the printername, not \\server\printername
2073 if ( info->servername[0] != '\0' ) {
2074 trim_string(info->printername, info->servername, NULL);
2075 trim_char(info->printername, '\\', '\0');
2076 info->servername[0]='\0';
2080 * JFM: one day I'll forget.
2081 * below that's info->portname because that's the SAMBA sharename
2082 * and I made NT 'thinks' it's the portname
2083 * the info->sharename is the thing you can name when you add a printer
2084 * that's the short-name when you create shared printer for 95/98
2085 * So I've made a limitation in SAMBA: you can only have 1 printer model
2086 * behind a SAMBA share.
2094 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2097 info->default_priority,
2114 info->printprocessor,
2118 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2120 len += pack_values( &info->data, buf+len, buflen-len );
2122 if (buflen != len) {
2125 tb = (char *)Realloc(buf, len);
2127 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2137 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2140 kbuf.dsize = strlen(key)+1;
2144 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2147 if (!W_ERROR_IS_OK(ret))
2148 DEBUG(8, ("error updating printer to tdb on disk\n"));
2152 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2153 info->sharename, info->drivername, info->portname, len));
2159 /****************************************************************************
2160 Malloc and return an NT devicemode.
2161 ****************************************************************************/
2163 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2166 char adevice[MAXDEVICENAME];
2167 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2169 if (nt_devmode == NULL) {
2170 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2174 ZERO_STRUCTP(nt_devmode);
2176 safe_strcpy(adevice, default_devicename, sizeof(adevice)-1);
2177 fstrcpy(nt_devmode->devicename, adevice);
2179 fstrcpy(nt_devmode->formname, "Letter");
2181 nt_devmode->specversion = 0x0401;
2182 nt_devmode->driverversion = 0x0400;
2183 nt_devmode->size = 0x00DC;
2184 nt_devmode->driverextra = 0x0000;
2185 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2186 DEFAULTSOURCE | COPIES | SCALE |
2187 PAPERSIZE | ORIENTATION;
2188 nt_devmode->orientation = 1;
2189 nt_devmode->papersize = PAPER_LETTER;
2190 nt_devmode->paperlength = 0;
2191 nt_devmode->paperwidth = 0;
2192 nt_devmode->scale = 0x64;
2193 nt_devmode->copies = 1;
2194 nt_devmode->defaultsource = BIN_FORMSOURCE;
2195 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2196 nt_devmode->color = COLOR_MONOCHROME;
2197 nt_devmode->duplex = DUP_SIMPLEX;
2198 nt_devmode->yresolution = 0;
2199 nt_devmode->ttoption = TT_SUBDEV;
2200 nt_devmode->collate = COLLATE_FALSE;
2201 nt_devmode->icmmethod = 0;
2202 nt_devmode->icmintent = 0;
2203 nt_devmode->mediatype = 0;
2204 nt_devmode->dithertype = 0;
2206 /* non utilisés par un driver d'imprimante */
2207 nt_devmode->logpixels = 0;
2208 nt_devmode->bitsperpel = 0;
2209 nt_devmode->pelswidth = 0;
2210 nt_devmode->pelsheight = 0;
2211 nt_devmode->displayflags = 0;
2212 nt_devmode->displayfrequency = 0;
2213 nt_devmode->reserved1 = 0;
2214 nt_devmode->reserved2 = 0;
2215 nt_devmode->panningwidth = 0;
2216 nt_devmode->panningheight = 0;
2218 nt_devmode->private = NULL;
2222 /****************************************************************************
2223 Deepcopy an NT devicemode.
2224 ****************************************************************************/
2226 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2228 NT_DEVICEMODE *new_nt_devicemode = NULL;
2230 if ( !nt_devicemode )
2233 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2234 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2238 new_nt_devicemode->private = NULL;
2239 if (nt_devicemode->private != NULL) {
2240 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2241 SAFE_FREE(new_nt_devicemode);
2242 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2247 return new_nt_devicemode;
2250 /****************************************************************************
2251 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2252 ****************************************************************************/
2254 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2256 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2258 if(nt_devmode == NULL)
2261 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2263 SAFE_FREE(nt_devmode->private);
2264 SAFE_FREE(*devmode_ptr);
2267 /****************************************************************************
2268 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2269 ****************************************************************************/
2270 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2272 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2273 NT_PRINTER_DATA *data;
2279 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2281 free_nt_devicemode(&info->devmode);
2283 /* clean up all registry keys */
2286 for ( i=0; i<data->num_keys; i++ ) {
2287 SAFE_FREE( data->keys[i].name );
2288 regval_ctr_destroy( &data->keys[i].values );
2290 SAFE_FREE( data->keys );
2292 /* finally the top level structure */
2294 SAFE_FREE( *info_ptr );
2298 /****************************************************************************
2299 ****************************************************************************/
2300 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2304 NT_DEVICEMODE devmode;
2306 ZERO_STRUCT(devmode);
2308 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2310 if (!*nt_devmode) return len;
2312 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2316 &devmode.specversion,
2317 &devmode.driverversion,
2319 &devmode.driverextra,
2320 &devmode.orientation,
2322 &devmode.paperlength,
2323 &devmode.paperwidth,
2326 &devmode.defaultsource,
2327 &devmode.printquality,
2330 &devmode.yresolution,
2336 &devmode.bitsperpel,
2338 &devmode.pelsheight,
2339 &devmode.displayflags,
2340 &devmode.displayfrequency,
2344 &devmode.dithertype,
2347 &devmode.panningwidth,
2348 &devmode.panningheight,
2351 if (devmode.private) {
2352 /* the len in tdb_unpack is an int value and
2353 * devmode.driverextra is only a short
2355 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2356 devmode.driverextra=(uint16)extra_len;
2358 /* check to catch an invalid TDB entry so we don't segfault */
2359 if (devmode.driverextra == 0) {
2360 devmode.private = NULL;
2364 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2366 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2367 if (devmode.private)
2368 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2373 /****************************************************************************
2374 Allocate and initialize a new slot.
2375 ***************************************************************************/
2377 static int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
2382 if ( !data || !name )
2385 /* allocate another slot in the NT_PRINTER_KEY array */
2387 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2391 key_index = data->num_keys;
2393 /* initialze new key */
2396 data->keys[key_index].name = strdup( name );
2398 ZERO_STRUCTP( &data->keys[key_index].values );
2400 regval_ctr_init( &data->keys[key_index].values );
2402 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2407 /****************************************************************************
2408 search for a registry key name in the existing printer data
2409 ***************************************************************************/
2411 int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
2416 if ( !data || !name )
2419 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2421 /* loop over all existing keys */
2423 for ( i=0; i<data->num_keys; i++ ) {
2424 if ( strequal(data->keys[i].name, name) ) {
2425 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2435 /****************************************************************************
2436 ***************************************************************************/
2438 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **subkeys )
2442 int num_subkeys = 0;
2444 fstring *ptr, *subkeys_ptr = NULL;
2450 for ( i=0; i<data->num_keys; i++ ) {
2451 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
2452 /* match sure it is a subkey and not the key itself */
2454 key_len = strlen( key );
2455 if ( strlen(data->keys[i].name) == key_len )
2458 /* get subkey path */
2460 p = data->keys[i].name + key_len;
2463 fstrcpy( subkeyname, p );
2464 if ( (p = strchr( subkeyname, '\\' )) )
2467 /* don't add a key more than once */
2469 for ( j=0; j<num_subkeys; j++ ) {
2470 if ( strequal( subkeys_ptr[j], subkeyname ) )
2474 if ( j != num_subkeys )
2477 /* found a match, so allocate space and copy the name */
2479 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2480 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2482 SAFE_FREE( subkeys );
2487 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2493 /* tag of the end */
2496 fstrcpy(subkeys_ptr[num_subkeys], "" );
2498 *subkeys = subkeys_ptr;
2504 static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2507 smb_ucs2_t conv_str[1024];
2510 regval_ctr_delvalue(ctr, val_name);
2511 str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
2512 STR_TERMINATE | STR_NOALIGN);
2513 regval_ctr_addvalue(ctr, val_name, REG_SZ,
2514 (char *) conv_str, str_size);
2517 static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2520 regval_ctr_delvalue(ctr, val_name);
2521 regval_ctr_addvalue(ctr, val_name, REG_DWORD,
2522 (char *) &dword, sizeof(dword));
2525 static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2528 uint8 bin_bool = (b ? 1 : 0);
2529 regval_ctr_delvalue(ctr, val_name);
2530 regval_ctr_addvalue(ctr, val_name, REG_BINARY,
2531 (char *) &bin_bool, sizeof(bin_bool));
2534 static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
2535 const char *multi_sz)
2537 smb_ucs2_t *conv_strs = NULL;
2540 /* a multi-sz has to have a null string terminator, i.e., the last
2541 string must be followed by two nulls */
2542 str_size = (strlen(multi_sz) + 2) * sizeof(smb_ucs2_t);
2543 conv_strs = calloc(str_size, 1);
2545 push_ucs2(NULL, conv_strs, multi_sz, str_size,
2546 STR_TERMINATE | STR_NOALIGN);
2548 regval_ctr_delvalue(ctr, val_name);
2549 regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
2550 (char *) conv_strs, str_size);
2551 safe_free(conv_strs);
2555 /****************************************************************************
2556 * Map the NT_PRINTER_INFO_LEVEL_2 data into DsSpooler keys for publishing.
2558 * @param info2 NT_PRINTER_INFO_LEVEL_2 describing printer - gets modified
2559 * @return BOOL indicating success or failure
2560 ***************************************************************************/
2562 static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
2564 REGVAL_CTR *ctr = NULL;
2566 char *allocated_string = NULL;
2567 const char *ascii_str;
2570 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2571 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2572 ctr = &info2->data.keys[i].values;
2574 map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);
2575 map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname());
2577 get_mydnsfullname(longname);
2578 map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
2580 asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
2581 map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
2582 SAFE_FREE(allocated_string);
2584 map_dword_into_ctr(ctr, SPOOL_REG_VERSIONNUMBER, 4);
2585 map_sz_into_ctr(ctr, SPOOL_REG_DRIVERNAME, info2->drivername);
2586 map_sz_into_ctr(ctr, SPOOL_REG_LOCATION, info2->location);
2587 map_sz_into_ctr(ctr, SPOOL_REG_DESCRIPTION, info2->comment);
2588 map_single_multi_sz_into_ctr(ctr, SPOOL_REG_PORTNAME, info2->portname);
2589 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
2590 map_dword_into_ctr(ctr, SPOOL_REG_PRINTSTARTTIME, info2->starttime);
2591 map_dword_into_ctr(ctr, SPOOL_REG_PRINTENDTIME, info2->untiltime);
2592 map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
2594 map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
2595 (info2->attributes &
2596 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
2598 switch (info2->attributes & 0x3) {
2600 ascii_str = SPOOL_REGVAL_PRINTWHILESPOOLING;
2603 ascii_str = SPOOL_REGVAL_PRINTAFTERSPOOLED;
2606 ascii_str = SPOOL_REGVAL_PRINTDIRECT;
2609 ascii_str = "unknown";
2611 map_sz_into_ctr(ctr, SPOOL_REG_PRINTSPOOLING, ascii_str);
2616 static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
2620 REGVAL_CTR *ctr=NULL;
2622 /* find the DsSpooler key */
2623 if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0)
2624 i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY);
2625 ctr = &info2->data.keys[i].values;
2627 regval_ctr_delvalue(ctr, "objectGUID");
2628 regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,
2629 (char *) &guid, sizeof(struct uuid));
2632 static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)
2635 TALLOC_CTX *ctx = talloc_init("publish_it");
2636 ADS_MODLIST mods = ads_init_mods(ctx);
2637 char *prt_dn = NULL, *srv_dn, *srv_cn_0;
2638 char *srv_dn_utf8, **srv_cn_utf8;
2641 const char *attrs[] = {"objectGUID", NULL};
2643 WERROR win_rc = WERR_OK;
2646 /* set the DsSpooler info and attributes */
2647 if (!(map_nt_printer_info2_to_dsspooler(printer->info_2)))
2649 printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
2650 win_rc = mod_a_printer(*printer, 2);
2651 if (!W_ERROR_IS_OK(win_rc)) {
2652 DEBUG(3, ("err %d saving data\n",
2653 W_ERROR_V(win_rc)));
2657 /* Build the ads mods */
2658 get_local_printer_publishing_data(ctx, &mods,
2659 &printer->info_2->data);
2660 ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
2661 printer->info_2->sharename);
2663 /* initial ads structure */
2665 ads = ads_init(NULL, NULL, NULL);
2667 DEBUG(3, ("ads_init() failed\n"));
2668 return WERR_SERVER_UNAVAILABLE;
2670 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2671 SAFE_FREE(ads->auth.password);
2672 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2675 /* ads_connect() will find the DC for us */
2676 ads_rc = ads_connect(ads);
2677 if (!ADS_ERR_OK(ads_rc)) {
2678 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2680 return WERR_ACCESS_DENIED;
2683 /* figure out where to publish */
2684 ads_find_machine_acct(ads, &res, global_myname());
2686 /* We use ldap_get_dn here as we need the answer
2687 * in utf8 to call ldap_explode_dn(). JRA. */
2689 srv_dn_utf8 = ldap_get_dn(ads->ld, res);
2692 return WERR_SERVER_UNAVAILABLE;
2694 ads_msgfree(ads, res);
2695 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
2697 ldap_memfree(srv_dn_utf8);
2699 return WERR_SERVER_UNAVAILABLE;
2701 /* Now convert to CH_UNIX. */
2702 if (pull_utf8_allocate(&srv_dn, srv_dn_utf8) == (size_t)-1) {
2703 ldap_memfree(srv_dn_utf8);
2704 ldap_memfree(srv_cn_utf8);
2706 return WERR_SERVER_UNAVAILABLE;
2708 if (pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) {
2709 ldap_memfree(srv_dn_utf8);
2710 ldap_memfree(srv_cn_utf8);
2713 return WERR_SERVER_UNAVAILABLE;
2716 ldap_memfree(srv_dn_utf8);
2717 ldap_memfree(srv_cn_utf8);
2719 asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0,
2720 printer->info_2->sharename, srv_dn);
2723 SAFE_FREE(srv_cn_0);
2726 ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
2727 if (LDAP_ALREADY_EXISTS == ads_rc.err.rc)
2728 ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods);
2730 /* retreive the guid and store it locally */
2731 if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
2732 ads_pull_guid(ads, res, &guid);
2733 ads_msgfree(ads, res);
2734 store_printer_guid(printer->info_2, guid);
2735 win_rc = mod_a_printer(*printer, 2);
2744 WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer)
2749 char *prt_dn = NULL;
2752 printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
2753 win_rc = mod_a_printer(*printer, 2);
2754 if (!W_ERROR_IS_OK(win_rc)) {
2755 DEBUG(3, ("err %d saving data\n",
2756 W_ERROR_V(win_rc)));
2760 ads = ads_init(NULL, NULL, NULL);
2762 DEBUG(3, ("ads_init() failed\n"));
2763 return WERR_SERVER_UNAVAILABLE;
2765 setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
2766 SAFE_FREE(ads->auth.password);
2767 ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
2770 /* ads_connect() will find the DC for us */
2771 ads_rc = ads_connect(ads);
2772 if (!ADS_ERR_OK(ads_rc)) {
2773 DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
2775 return WERR_ACCESS_DENIED;
2778 /* remove the printer from the directory */
2779 ads_rc = ads_find_printer_on_server(ads, &res,
2780 printer->info_2->sharename, global_myname());
2781 if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
2782 prt_dn = ads_get_dn(ads, res);
2783 ads_msgfree(ads, res);
2784 ads_rc = ads_del_dn(ads, prt_dn);
2785 ads_memfree(ads, prt_dn);
2792 /****************************************************************************
2793 * Publish a printer in the directory
2795 * @param snum describing printer service
2796 * @return WERROR indicating status of publishing
2797 ***************************************************************************/
2799 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2801 NT_PRINTER_INFO_LEVEL *printer = NULL;
2804 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2805 if (!W_ERROR_IS_OK(win_rc))
2809 case SPOOL_DS_PUBLISH:
2810 case SPOOL_DS_UPDATE:
2811 win_rc = publish_it(printer);
2813 case SPOOL_DS_UNPUBLISH:
2814 win_rc = unpublish_it(printer);
2817 win_rc = WERR_NOT_SUPPORTED;
2821 free_a_printer(&printer, 2);
2825 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2828 NT_PRINTER_INFO_LEVEL *printer = NULL;
2830 REGISTRY_VALUE *guid_val;
2835 win_rc = get_a_printer(print_hnd, &printer, 2, lp_servicename(snum));
2836 if (!W_ERROR_IS_OK(win_rc))
2839 if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED))
2842 if ((i = lookup_printerkey(&printer->info_2->data,
2843 SPOOL_DSSPOOLER_KEY)) < 0)
2846 if (!(ctr = &printer->info_2->data.keys[i].values)) {
2850 if (!(guid_val = regval_ctr_getvalue(ctr, "objectGUID"))) {
2854 if (regval_size(guid_val) == sizeof(struct uuid))
2855 memcpy(guid, regval_data_p(guid_val), sizeof(struct uuid));
2861 WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
2865 BOOL is_printer_published(Printer_entry *print_hnd, int snum,
2871 /****************************************************************************
2872 ***************************************************************************/
2874 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
2876 NT_PRINTER_DATA *data;
2878 int removed_keys = 0;
2882 empty_slot = data->num_keys;
2885 return WERR_INVALID_PARAM;
2887 /* remove all keys */
2889 if ( !strlen(key) ) {
2890 for ( i=0; i<data->num_keys; i++ ) {
2891 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2892 data->keys[i].name));
2894 SAFE_FREE( data->keys[i].name );
2895 regval_ctr_destroy( &data->keys[i].values );
2898 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2901 SAFE_FREE( data->keys );
2902 ZERO_STRUCTP( data );
2907 /* remove a specific key (and all subkeys) */
2909 for ( i=0; i<data->num_keys; i++ ) {
2910 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
2911 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2912 data->keys[i].name));
2914 SAFE_FREE( data->keys[i].name );
2915 regval_ctr_destroy( &data->keys[i].values );
2917 /* mark the slot as empty */
2919 ZERO_STRUCTP( &data->keys[i] );
2923 /* find the first empty slot */
2925 for ( i=0; i<data->num_keys; i++ ) {
2926 if ( !data->keys[i].name ) {
2933 if ( i == data->num_keys )
2934 /* nothing was removed */
2935 return WERR_INVALID_PARAM;
2937 /* move everything down */
2939 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2940 if ( data->keys[i].name ) {
2941 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2942 ZERO_STRUCTP( &data->keys[i] );
2950 data->num_keys -= removed_keys;
2952 /* sanity check to see if anything is left */
2954 if ( !data->num_keys ) {
2955 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2957 SAFE_FREE( data->keys );
2958 ZERO_STRUCTP( data );
2964 /****************************************************************************
2965 ***************************************************************************/
2967 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
2969 WERROR result = WERR_OK;
2972 /* we must have names on non-zero length */
2974 if ( !key || !*key|| !value || !*value )
2975 return WERR_INVALID_NAME;
2977 /* find the printer key first */
2979 key_index = lookup_printerkey( &p2->data, key );
2980 if ( key_index == -1 )
2983 /* make sure the value exists so we can return the correct error code */
2985 if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) )
2986 return WERR_BADFILE;
2988 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2990 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2996 /****************************************************************************
2997 ***************************************************************************/
2999 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
3000 uint32 type, uint8 *data, int real_len )
3002 WERROR result = WERR_OK;
3005 /* we must have names on non-zero length */
3007 if ( !key || !*key|| !value || !*value )
3008 return WERR_INVALID_NAME;
3010 /* find the printer key first */
3012 key_index = lookup_printerkey( &p2->data, key );
3013 if ( key_index == -1 )
3014 key_index = add_new_printer_key( &p2->data, key );
3016 if ( key_index == -1 )
3019 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
3020 type, (const char *)data, real_len );
3022 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
3023 key, value, type, real_len ));
3028 /****************************************************************************
3029 ***************************************************************************/
3031 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
3035 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
3038 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
3041 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
3044 /****************************************************************************
3045 Unpack a list of registry values frem the TDB
3046 ***************************************************************************/
3048 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
3052 pstring string, valuename, keyname;
3056 REGISTRY_VALUE *regval_p;
3059 /* add the "PrinterDriverData" key first for performance reasons */
3061 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
3063 /* loop and unpack the rest of the registry values */
3067 /* check to see if there are any more registry values */
3070 len += tdb_unpack(buf+len, buflen-len, "p", ®val_p);
3074 /* unpack the next regval */
3076 len += tdb_unpack(buf+len, buflen-len, "fdB",
3083 * break of the keyname from the value name.
3084 * Valuenames can have embedded '\'s so be careful.
3085 * only support one level of keys. See the
3086 * "Konica Fiery S300 50C-K v1.1. enu" 2k driver.
3090 str = strchr_m( string, '\\');
3092 /* Put in "PrinterDriverData" is no key specified */
3095 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
3096 pstrcpy( valuename, string );
3100 pstrcpy( keyname, string );
3101 pstrcpy( valuename, str+1 );
3104 /* see if we need a new key */
3106 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
3107 key_index = add_new_printer_key( printer_data, keyname );
3109 if ( key_index == -1 ) {
3110 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
3115 /* add the new value */
3117 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size );
3119 SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */
3121 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
3127 /****************************************************************************
3128 ***************************************************************************/
3130 static void map_to_os2_driver(fstring drivername)
3132 static BOOL initialised=False;
3133 static fstring last_from,last_to;
3134 char *mapfile = lp_os2_driver_map();
3135 char **lines = NULL;
3139 if (!strlen(drivername))
3146 *last_from = *last_to = 0;
3150 if (strequal(drivername,last_from)) {
3151 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
3152 fstrcpy(drivername,last_to);
3156 lines = file_lines_load(mapfile, &numlines);
3157 if (numlines == 0) {
3158 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
3162 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
3164 for( i = 0; i < numlines; i++) {
3165 char *nt_name = lines[i];
3166 char *os2_name = strchr(nt_name,'=');
3173 while (isspace(*nt_name))
3176 if (!*nt_name || strchr("#;",*nt_name))
3180 int l = strlen(nt_name);
3181 while (l && isspace(nt_name[l-1])) {
3187 while (isspace(*os2_name))
3191 int l = strlen(os2_name);
3192 while (l && isspace(os2_name[l-1])) {
3198 if (strequal(nt_name,drivername)) {
3199 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
3200 fstrcpy(last_from,drivername);
3201 fstrcpy(last_to,os2_name);
3202 fstrcpy(drivername,os2_name);
3203 file_lines_free(lines);
3208 file_lines_free(lines);
3211 /****************************************************************************
3212 Get a default printer info 2 struct.
3213 ****************************************************************************/
3214 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3217 NT_PRINTER_INFO_LEVEL_2 info;
3221 snum = lp_servicenumber(sharename);
3223 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3224 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
3225 get_called_name(), sharename);
3226 fstrcpy(info.sharename, sharename);
3227 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
3229 /* by setting the driver name to an empty string, a local NT admin
3230 can now run the **local** APW to install a local printer driver
3231 for a Samba shared printer in 2.2. Without this, drivers **must** be
3232 installed on the Samba server for NT clients --jerry */
3233 #if 0 /* JERRY --do not uncomment-- */
3234 if (!*info.drivername)
3235 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
3239 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
3241 pstrcpy(info.comment, "");
3242 fstrcpy(info.printprocessor, "winprint");
3243 fstrcpy(info.datatype, "RAW");
3245 info.attributes = PRINTER_ATTRIBUTE_SAMBA;
3247 info.starttime = 0; /* Minutes since 12:00am GMT */
3248 info.untiltime = 0; /* Minutes since 12:00am GMT */
3250 info.default_priority = 1;
3251 info.setuptime = (uint32)time(NULL);
3254 * I changed this as I think it is better to have a generic
3255 * DEVMODE than to crash Win2k explorer.exe --jerry
3256 * See the HP Deskjet 990c Win2k drivers for an example.
3258 * However the default devmode appears to cause problems
3259 * with the HP CLJ 8500 PCL driver. Hence the addition of
3260 * the "default devmode" parameter --jerry 22/01/2002
3263 if (lp_default_devmode(snum)) {
3264 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
3268 info.devmode = NULL;
3271 /* This will get the current RPC talloc context, but we should be
3272 passing this as a parameter... fixme... JRA ! */
3274 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
3277 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
3279 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
3287 free_nt_devicemode(&info.devmode);
3288 return WERR_ACCESS_DENIED;
3291 /****************************************************************************
3292 ****************************************************************************/
3293 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sharename)
3296 NT_PRINTER_INFO_LEVEL_2 info;
3298 TDB_DATA kbuf, dbuf;
3299 fstring printername;
3300 char adevice[MAXDEVICENAME];
3304 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
3307 kbuf.dsize = strlen(key)+1;
3309 dbuf = tdb_fetch(tdb_printers, kbuf);
3311 return get_a_printer_2_default(info_ptr, sharename);
3313 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
3316 &info.default_priority,
3333 info.printprocessor,
3337 /* Samba has to have shared raw drivers. */
3338 info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
3339 info.attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
3341 /* Restore the stripped strings. */
3342 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
3343 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
3345 fstrcpy(info.printername, printername);
3347 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3350 * Some client drivers freak out if there is a NULL devmode
3351 * (probably the driver is not checking before accessing
3352 * the devmode pointer) --jerry
3354 * See comments in get_a_printer_2_default()
3357 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode) {
3358 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
3360 info.devmode = construct_nt_devicemode(printername);
3363 safe_strcpy(adevice, info.printername, sizeof(adevice)-1);
3365 fstrcpy(info.devmode->devicename, adevice);
3368 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
3370 /* This will get the current RPC talloc context, but we should be
3371 passing this as a parameter... fixme... JRA ! */
3373 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
3375 /* Fix for OS/2 drivers. */
3377 if (get_remote_arch() == RA_OS2)
3378 map_to_os2_driver(info.drivername);
3380 SAFE_FREE(dbuf.dptr);
3381 *info_ptr=memdup(&info, sizeof(info));
3383 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
3384 sharename, info.printername, info.drivername));
3389 /****************************************************************************
3390 Debugging function, dump at level 6 the struct in the logs.
3391 ****************************************************************************/
3392 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3395 NT_PRINTER_INFO_LEVEL_2 *info2;
3397 DEBUG(106,("Dumping printer at level [%d]\n", level));
3402 if (printer.info_2 == NULL)
3406 info2=printer.info_2;
3408 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3409 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3410 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3411 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3412 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3413 DEBUGADD(106,("status:[%d]\n", info2->status));
3414 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3415 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3416 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3417 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3418 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3420 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3421 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3422 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3423 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3424 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3425 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3426 DEBUGADD(106,("location:[%s]\n", info2->location));
3427 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3428 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3429 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3430 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3436 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3444 /****************************************************************************
3445 Update the changeid time.
3446 This is SO NASTY as some drivers need this to change, others need it
3447 static. This value will change every second, and I must hope that this
3448 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3450 ****************************************************************************/
3452 static uint32 rev_changeid(void)
3456 get_process_uptime(&tv);
3459 /* Return changeid as msec since spooler restart */
3460 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3463 * This setting seems to work well but is too untested
3464 * to replace the above calculation. Left in for experiementation
3465 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3467 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3471 /********************************************************************
3472 Send a message to all smbds about the printer that just changed
3473 ********************************************************************/
3475 static BOOL send_printer_mod_msg( char* printername )
3477 int len = strlen(printername);
3482 DEBUG(10,("send_printer_mod_msg: Sending message about printer change [%s]\n",
3485 /* spam everyone that we just changed this printer */
3487 message_send_all( conn_tdb_ctx(), MSG_PRINTER_MOD, printername, len+1, False, NULL );
3493 * The function below are the high level ones.
3494 * only those ones must be called from the spoolss code.
3498 /****************************************************************************
3499 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3500 ****************************************************************************/
3502 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3506 dump_a_printer(printer, level);
3509 * invalidate cache for all open handles to this printer.
3510 * cache for a given handle will be updated on the next
3514 invalidate_printer_hnd_cache( printer.info_2->sharename );
3515 send_printer_mod_msg( printer.info_2->sharename );
3521 * Update the changestamp. Emperical tests show that the
3522 * ChangeID is always updated,but c_setprinter is
3523 * global spooler variable (not per printer).
3526 /* ChangeID **must** be increasing over the lifetime
3527 of client's spoolss service in order for the
3528 client's cache to show updates */
3530 printer.info_2->changeid = rev_changeid();
3533 * Because one day someone will ask:
3534 * NT->NT An admin connection to a remote
3535 * printer show changes imeediately in
3536 * the properities dialog
3538 * A non-admin connection will only show the
3539 * changes after viewing the properites page
3540 * 2 times. Seems to be related to a
3541 * race condition in the client between the spooler
3542 * updating the local cache and the Explorer.exe GUI
3543 * actually displaying the properties.
3545 * This is fixed in Win2k. admin/non-admin
3546 * connections both display changes immediately.
3551 result=update_a_printer_2(printer.info_2);
3556 result=WERR_UNKNOWN_LEVEL;
3563 /****************************************************************************
3564 Initialize printer devmode & data with previously saved driver init values.
3565 ****************************************************************************/
3567 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3571 TDB_DATA kbuf, dbuf;
3572 NT_PRINTER_INFO_LEVEL_2 info;
3578 * Delete any printer data 'values' already set. When called for driver
3579 * replace, there will generally be some, but during an add printer, there
3580 * should not be any (if there are delete them).
3583 delete_all_printer_data( info_ptr, "" );
3585 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3588 kbuf.dsize = strlen(key)+1;
3590 dbuf = tdb_fetch(tdb_drivers, kbuf);
3593 * When changing to a driver that has no init info in the tdb, remove
3594 * the previous drivers init info and leave the new on blank.
3596 free_nt_devicemode(&info_ptr->devmode);
3601 * Get the saved DEVMODE..
3604 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3607 * The saved DEVMODE contains the devicename from the printer used during
3608 * the initialization save. Change it to reflect the new printer.
3611 if ( info.devmode ) {
3612 ZERO_STRUCT(info.devmode->devicename);
3613 fstrcpy(info.devmode->devicename, info_ptr->printername);
3617 * NT/2k does not change out the entire DeviceMode of a printer
3618 * when changing the driver. Only the driverextra, private, &
3619 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3621 * Later examination revealed that Windows NT/2k does reset the
3622 * the printer's device mode, bit **only** when you change a
3623 * property of the device mode such as the page orientation.
3628 /* Bind the saved DEVMODE to the new the printer */
3630 free_nt_devicemode(&info_ptr->devmode);
3631 info_ptr->devmode = info.devmode;
3633 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3634 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3636 /* Add the printer data 'values' to the new printer */
3638 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3641 SAFE_FREE(dbuf.dptr);
3646 /****************************************************************************
3647 Initialize printer devmode & data with previously saved driver init values.
3648 When a printer is created using AddPrinter, the drivername bound to the
3649 printer is used to lookup previously saved driver initialization info, which
3650 is bound to the new printer.
3651 ****************************************************************************/
3653 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3655 BOOL result = False;
3659 result = set_driver_init_2(printer->info_2);
3663 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3671 /****************************************************************************
3672 Delete driver init data stored for a specified driver
3673 ****************************************************************************/
3675 BOOL del_driver_init(char *drivername)
3680 if (!drivername || !*drivername) {
3681 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3685 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3688 kbuf.dsize = strlen(key)+1;
3690 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3692 return (tdb_delete(tdb_drivers, kbuf) == 0);
3695 /****************************************************************************
3696 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3697 in the tdb. Note: this is different from the driver entry and the printer
3698 entry. There should be a single driver init entry for each driver regardless
3699 of whether it was installed from NT or 2K. Technically, they should be
3700 different, but they work out to the same struct.
3701 ****************************************************************************/
3703 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3707 int buflen, len, ret;
3708 TDB_DATA kbuf, dbuf;
3715 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3717 len += pack_values( &info->data, buf+len, buflen-len );
3719 if (buflen != len) {
3722 tb = (char *)Realloc(buf, len);
3724 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3734 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3737 kbuf.dsize = strlen(key)+1;
3741 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3745 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3749 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3750 info->sharename, info->drivername));
3755 /****************************************************************************
3756 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3757 ****************************************************************************/
3759 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3763 dump_a_printer(printer, level);
3767 result = update_driver_init_2(printer.info_2);
3777 /****************************************************************************
3778 Convert the printer data value, a REG_BINARY array, into an initialization
3779 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3780 got to keep the endians happy :).
3781 ****************************************************************************/
3783 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3785 BOOL result = False;
3789 ZERO_STRUCT(devmode);
3791 prs_init(&ps, 0, ctx, UNMARSHALL);
3792 ps.data_p = (char *)data;
3793 ps.buffer_size = data_len;
3795 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3796 result = convert_devicemode("", &devmode, &nt_devmode);
3798 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3803 /****************************************************************************
3804 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3806 1. Use the driver's config DLL to this UNC printername and:
3807 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3808 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3809 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3811 The last step triggers saving the "driver initialization" information for
3812 this printer into the tdb. Later, new printers that use this driver will
3813 have this initialization information bound to them. This simulates the
3814 driver initialization, as if it had run on the Samba server (as it would
3817 The Win32 client side code requirement sucks! But until we can run arbitrary
3818 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3820 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3821 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3822 about it and you will realize why. JRR 010720
3823 ****************************************************************************/
3825 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3827 WERROR status = WERR_OK;
3828 TALLOC_CTX *ctx = NULL;
3829 NT_DEVICEMODE *nt_devmode = NULL;
3830 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3833 * When the DEVMODE is already set on the printer, don't try to unpack it.
3835 DEBUG(8,("save_driver_init_2: Enter...\n"));
3837 if ( !printer->info_2->devmode && data_len ) {
3839 * Set devmode on printer info, so entire printer initialization can be
3843 if ((ctx = talloc_init("save_driver_init_2")) == NULL)
3846 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3847 status = WERR_NOMEM;
3851 ZERO_STRUCTP(nt_devmode);
3854 * The DEVMODE is held in the 'data' component of the param in raw binary.
3855 * Convert it to to a devmode structure
3857 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3858 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3859 status = WERR_INVALID_PARAM;
3863 printer->info_2->devmode = nt_devmode;
3867 * Pack up and add (or update) the DEVMODE and any current printer data to
3868 * a 'driver init' element in the tdb
3872 if ( update_driver_init(*printer, 2) != 0 ) {
3873 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3874 status = WERR_NOMEM;
3879 * If driver initialization info was successfully saved, set the current
3880 * printer to match it. This allows initialization of the current printer
3881 * as well as the driver.
3883 status = mod_a_printer(*printer, 2);
3884 if (!W_ERROR_IS_OK(status)) {
3885 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3886 printer->info_2->printername));
3890 talloc_destroy(ctx);
3891 free_nt_devicemode( &nt_devmode );
3893 printer->info_2->devmode = tmp_devmode;
3898 /****************************************************************************
3899 Update the driver init info (DEVMODE and specifics) for a printer
3900 ****************************************************************************/
3902 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3904 WERROR status = WERR_OK;
3908 status = save_driver_init_2( printer, data, data_len );
3911 status = WERR_UNKNOWN_LEVEL;
3918 /****************************************************************************
3919 Deep copy a NT_PRINTER_DATA
3920 ****************************************************************************/
3922 static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src )
3924 int i, j, num_vals, new_key_index;
3925 REGVAL_CTR *src_key, *dst_key;
3928 return NT_STATUS_NO_MEMORY;
3930 for ( i=0; i<src->num_keys; i++ ) {
3932 /* create a new instance of the printerkey in the destination
3933 printer_data object */
3935 new_key_index = add_new_printer_key( dst, src->keys[i].name );
3936 dst_key = &dst->keys[new_key_index].values;
3938 src_key = &src->keys[i].values;
3939 num_vals = regval_ctr_numvals( src_key );
3941 /* dup the printer entire printer key */
3943 for ( j=0; j<num_vals; j++ ) {
3944 regval_ctr_copyvalue( dst_key, regval_ctr_specific_value(src_key, j) );
3948 return NT_STATUS_OK;
3951 /****************************************************************************
3952 Deep copy a NT_PRINTER_INFO_LEVEL_2 structure using malloc()'d memeory
3954 ****************************************************************************/
3956 NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer )
3958 NT_PRINTER_INFO_LEVEL_2 *copy;
3963 if ( !(copy = (NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2))) )
3966 memcpy( copy, printer, sizeof(NT_PRINTER_INFO_LEVEL_2) );
3968 /* malloc()'d members copied here */
3970 copy->devmode = dup_nt_devicemode( printer->devmode );
3972 ZERO_STRUCT( copy->data );
3973 copy_printer_data( ©->data, &printer->data );
3975 /* this is talloc()'d; very ugly that we have a structure that
3976 is half malloc()'d and half talloc()'d but that is the way
3977 that the PRINTER_INFO stuff is written right now. --jerry */
3979 copy->secdesc_buf = dup_sec_desc_buf( ctx, printer->secdesc_buf );
3984 /****************************************************************************
3985 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3987 Previously the code had a memory allocation problem because it always
3988 used the TALLOC_CTX from the Printer_entry*. This context lasts
3989 as a long as the original handle is open. So if the client made a lot
3990 of getprinter[data]() calls, the memory usage would climb. Now we use
3991 a short lived TALLOC_CTX for printer_info_2 objects returned. We
3992 still use the Printer_entry->ctx for maintaining the cache copy though
3993 since that object must live as long as the handle by definition.
3996 ****************************************************************************/
3998 WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
3999 const char *sharename)
4002 NT_PRINTER_INFO_LEVEL *printer = NULL;
4006 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
4010 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4011 DEBUG(0,("get_a_printer: malloc fail.\n"));
4014 ZERO_STRUCTP(printer);
4017 * check for cache first. A Printer handle cannot changed
4018 * to another printer object so we only check that the printer
4019 * is actually for a printer and that the printer_info pointer
4023 && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)
4024 && print_hnd->printer_info )
4026 /* get_talloc_ctx() works here because we need a short
4027 lived talloc context */
4029 if ( !(printer->info_2 = dup_printer_2(get_talloc_ctx(), print_hnd->printer_info->info_2)) )
4031 DEBUG(0,("get_a_printer: unable to copy cached printer info!\n"));
4037 DEBUG(10,("get_a_printer: using cached copy of printer_info_2\n"));
4039 *pp_printer = printer;
4045 /* no cache for this handle; see if we can match one from another handle.
4046 Make sure to use a short lived talloc ctx */
4049 result = find_printer_in_print_hnd_cache(get_talloc_ctx(), &printer->info_2, sharename);
4051 /* fail to disk if we don't have it with any open handle */
4053 if ( !print_hnd || !W_ERROR_IS_OK(result) )
4054 result = get_a_printer_2(&printer->info_2, sharename);
4056 /* we have a new printer now. Save it with this handle */
4058 if ( W_ERROR_IS_OK(result) ) {
4059 dump_a_printer(*printer, level);
4061 /* save a copy in cache */
4062 if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) {
4063 if ( !print_hnd->printer_info )
4064 print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL));
4066 if ( print_hnd->printer_info ) {
4067 /* make sure to use the handle's talloc ctx here since
4068 the printer_2 object must last until the handle is closed */
4070 print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2);
4072 /* don't fail the lookup just because the cache update failed */
4073 if ( !print_hnd->printer_info->info_2 )
4074 DEBUG(0,("get_a_printer: unable to copy new printer info!\n"));
4077 *pp_printer = printer;
4085 result=WERR_UNKNOWN_LEVEL;
4089 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
4094 /****************************************************************************
4095 Deletes a NT_PRINTER_INFO_LEVEL struct.
4096 ****************************************************************************/
4098 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
4101 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
4103 DEBUG(104,("freeing a printer at level [%d]\n", level));
4105 if (printer == NULL)
4110 if (printer->info_2 != NULL) {
4111 free_nt_printer_info_level_2(&printer->info_2);
4122 SAFE_FREE(*pp_printer);
4126 /****************************************************************************
4127 ****************************************************************************/
4128 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4131 DEBUG(104,("adding a printer at level [%d]\n", level));
4132 dump_a_printer_driver(driver, level);
4136 result=add_a_printer_driver_3(driver.info_3);
4140 result=add_a_printer_driver_6(driver.info_6);
4150 /****************************************************************************
4151 ****************************************************************************/
4153 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
4154 fstring drivername, const char *architecture, uint32 version)
4160 /* Sometime we just want any version of the driver */
4162 if ( version == DRIVER_ANY_VERSION ) {
4163 /* look for Win2k first and then for NT4 */
4164 result = get_a_printer_driver_3(&driver->info_3, drivername,
4167 if ( !W_ERROR_IS_OK(result) ) {
4168 result = get_a_printer_driver_3( &driver->info_3,
4169 drivername, architecture, 2 );
4172 result = get_a_printer_driver_3(&driver->info_3, drivername,
4173 architecture, version);
4182 if (W_ERROR_IS_OK(result))
4183 dump_a_printer_driver(*driver, level);
4188 /****************************************************************************
4189 ****************************************************************************/
4190 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
4197 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
4198 if (driver.info_3 != NULL)
4200 info3=driver.info_3;
4201 SAFE_FREE(info3->dependentfiles);
4202 ZERO_STRUCTP(info3);
4212 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
4213 if (driver.info_6 != NULL) {
4214 info6=driver.info_6;
4215 SAFE_FREE(info6->dependentfiles);
4216 SAFE_FREE(info6->previousnames);
4217 ZERO_STRUCTP(info6);
4233 /****************************************************************************
4234 Determine whether or not a particular driver is currently assigned
4236 ****************************************************************************/
4238 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
4241 int n_services = lp_numservices();
4242 NT_PRINTER_INFO_LEVEL *printer = NULL;
4247 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
4249 /* loop through the printers.tdb and check for the drivername */
4251 for (snum=0; snum<n_services; snum++) {
4252 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
4255 if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
4258 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
4259 free_a_printer( &printer, 2 );
4263 free_a_printer( &printer, 2 );
4266 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
4268 /* report that the driver is not in use by default */
4274 /**********************************************************************
4275 Check to see if a ogiven file is in use by *info
4276 *********************************************************************/
4278 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4285 if ( strequal(file, info->driverpath) )
4288 if ( strequal(file, info->datafile) )
4291 if ( strequal(file, info->configfile) )
4294 if ( strequal(file, info->helpfile) )
4297 /* see of there are any dependent files to examine */
4299 if ( !info->dependentfiles )
4302 while ( *info->dependentfiles[i] ) {
4303 if ( strequal(file, info->dependentfiles[i]) )
4312 /**********************************************************************
4313 Utility function to remove the dependent file pointed to by the
4314 input parameter from the list
4315 *********************************************************************/
4317 static void trim_dependent_file( fstring files[], int idx )
4320 /* bump everything down a slot */
4322 while( *files[idx+1] ) {
4323 fstrcpy( files[idx], files[idx+1] );
4332 /**********************************************************************
4333 Check if any of the files used by src are also used by drv
4334 *********************************************************************/
4336 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
4337 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
4339 BOOL in_use = False;
4345 /* check each file. Remove it from the src structure if it overlaps */
4347 if ( drv_file_in_use(src->driverpath, drv) ) {
4349 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
4350 fstrcpy( src->driverpath, "" );
4353 if ( drv_file_in_use(src->datafile, drv) ) {
4355 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
4356 fstrcpy( src->datafile, "" );
4359 if ( drv_file_in_use(src->configfile, drv) ) {
4361 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
4362 fstrcpy( src->configfile, "" );
4365 if ( drv_file_in_use(src->helpfile, drv) ) {
4367 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
4368 fstrcpy( src->helpfile, "" );
4371 /* are there any dependentfiles to examine? */
4373 if ( !src->dependentfiles )
4376 while ( *src->dependentfiles[i] ) {
4377 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
4379 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
4380 trim_dependent_file( src->dependentfiles, i );
4388 /****************************************************************************
4389 Determine whether or not a particular driver files are currently being
4390 used by any other driver.
4392 Return value is True if any files were in use by other drivers
4393 and False otherwise.
4395 Upon return, *info has been modified to only contain the driver files
4396 which are not in use
4397 ****************************************************************************/
4399 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
4404 fstring *list = NULL;
4405 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4410 version = info->cversion;
4412 /* loop over all driver versions */
4414 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
4416 /* get the list of drivers */
4419 ndrivers = get_ntdrivers(&list, info->environment, version);
4421 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
4422 ndrivers, info->environment, version));
4424 /* check each driver for overlap in files */
4426 for (i=0; i<ndrivers; i++) {
4427 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
4429 ZERO_STRUCT(driver);
4431 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
4436 /* check if d2 uses any files from d1 */
4437 /* only if this is a different driver than the one being deleted */
4439 if ( !strequal(info->name, driver.info_3->name) ) {
4440 if ( trim_overlap_drv_files(info, driver.info_3) ) {
4441 free_a_printer_driver(driver, 3);
4447 free_a_printer_driver(driver, 3);
4452 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
4454 driver.info_3 = info;
4456 if ( DEBUGLEVEL >= 20 )
4457 dump_a_printer_driver( driver, 3 );
4462 /****************************************************************************
4463 Actually delete the driver files. Make sure that
4464 printer_driver_files_in_use() return False before calling
4466 ****************************************************************************/
4468 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
4472 connection_struct *conn;
4482 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
4485 * Connect to the print$ share under the same account as the
4486 * user connected to the rpc pipe. Note we must be root to
4490 null_pw = data_blob( NULL, 0 );
4491 fstrcpy(res_type, "A:");
4493 conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
4497 DEBUG(0,("delete_driver_files: Unable to connect\n"));
4501 /* Save who we are - we are temporarily becoming the connection user. */
4503 if ( !become_user(conn, conn->vuid) ) {
4504 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4508 /* now delete the files; must strip the '\print$' string from
4511 if ( *info_3->driverpath ) {
4512 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4513 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4514 DEBUG(10,("deleting driverfile [%s]\n", s));
4515 unlink_internals(conn, 0, s);
4519 if ( *info_3->configfile ) {
4520 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4521 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4522 DEBUG(10,("deleting configfile [%s]\n", s));
4523 unlink_internals(conn, 0, s);
4527 if ( *info_3->datafile ) {
4528 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4529 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4530 DEBUG(10,("deleting datafile [%s]\n", s));
4531 unlink_internals(conn, 0, s);
4535 if ( *info_3->helpfile ) {
4536 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4537 driver_unix_convert(s, conn, NULL, &bad_path, &st);
4538 DEBUG(10,("deleting helpfile [%s]\n", s));
4539 unlink_internals(conn, 0, s);
4543 /* check if we are done removing files */
4545 if ( info_3->dependentfiles ) {
4546 while ( *info_3->dependentfiles[i] ) {
4549 /* bypass the "\print$" portion of the path */
4551 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
4552 driver_unix_convert(file, conn, NULL, &bad_path, &st);
4553 DEBUG(10,("deleting dependent file [%s]\n", file));
4554 unlink_internals(conn, 0, file );
4566 /****************************************************************************
4567 Remove a printer driver from the TDB. This assumes that the the driver was
4568 previously looked up.
4569 ***************************************************************************/
4571 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4572 uint32 version, BOOL delete_files )
4576 TDB_DATA kbuf, dbuf;
4577 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4579 /* delete the tdb data first */
4581 arch = get_short_archi(info_3->environment);
4582 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4583 arch, version, info_3->name);
4585 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4586 key, delete_files ? "TRUE" : "FALSE" ));
4588 ctr.info_3 = info_3;
4589 dump_a_printer_driver( ctr, 3 );
4592 kbuf.dsize=strlen(key)+1;
4594 /* check if the driver actually exists for this environment */
4596 dbuf = tdb_fetch( tdb_drivers, kbuf );
4598 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4599 return WERR_UNKNOWN_PRINTER_DRIVER;
4602 SAFE_FREE( dbuf.dptr );
4604 /* ok... the driver exists so the delete should return success */
4606 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4607 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4608 return WERR_ACCESS_DENIED;
4612 * now delete any associated files if delete_files == True
4613 * even if this part failes, we return succes because the
4614 * driver doesn not exist any more
4618 delete_driver_files( info_3, user );
4621 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4626 /****************************************************************************
4627 Store a security desc for a printer.
4628 ****************************************************************************/
4630 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4632 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4633 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4635 TALLOC_CTX *mem_ctx = NULL;
4639 mem_ctx = talloc_init("nt_printing_setsec");
4640 if (mem_ctx == NULL)
4643 /* The old owner and group sids of the security descriptor are not
4644 present when new ACEs are added or removed by changing printer
4645 permissions through NT. If they are NULL in the new security
4646 descriptor then copy them over from the old one. */
4648 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4649 DOM_SID *owner_sid, *group_sid;
4650 SEC_ACL *dacl, *sacl;
4651 SEC_DESC *psd = NULL;
4654 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4656 /* Pick out correct owner and group sids */
4658 owner_sid = secdesc_ctr->sec->owner_sid ?
4659 secdesc_ctr->sec->owner_sid :
4660 old_secdesc_ctr->sec->owner_sid;
4662 group_sid = secdesc_ctr->sec->grp_sid ?
4663 secdesc_ctr->sec->grp_sid :
4664 old_secdesc_ctr->sec->grp_sid;
4666 dacl = secdesc_ctr->sec->dacl ?
4667 secdesc_ctr->sec->dacl :
4668 old_secdesc_ctr->sec->dacl;
4670 sacl = secdesc_ctr->sec->sacl ?
4671 secdesc_ctr->sec->sacl :
4672 old_secdesc_ctr->sec->sacl;
4674 /* Make a deep copy of the security descriptor */
4676 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type,
4677 owner_sid, group_sid,
4682 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4685 if (!new_secdesc_ctr) {
4686 new_secdesc_ctr = secdesc_ctr;
4689 /* Store the security descriptor in a tdb */
4691 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4692 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4694 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4696 status = WERR_BADFUNC;
4700 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4702 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4705 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4706 status = WERR_BADFUNC;
4709 /* Free malloc'ed memory */
4715 talloc_destroy(mem_ctx);
4719 /****************************************************************************
4720 Construct a default security descriptor buffer for a printer.
4721 ****************************************************************************/
4723 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4727 SEC_ACL *psa = NULL;
4728 SEC_DESC_BUF *sdb = NULL;
4729 SEC_DESC *psd = NULL;
4733 /* Create an ACE where Everyone is allowed to print */
4735 init_sec_access(&sa, PRINTER_ACE_PRINT);
4736 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4737 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4739 /* Make the security descriptor owned by the Administrators group
4740 on the PDC of the domain. */
4742 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4743 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4746 /* Backup plan - make printer owned by admins.
4747 This should emulate a lanman printer as security
4748 settings can't be changed. */
4750 sid_copy(&owner_sid, get_global_sam_sid());
4751 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4754 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4755 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4756 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4757 SEC_ACE_FLAG_INHERIT_ONLY);
4759 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4760 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4761 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4763 /* The ACL revision number in rpc_secdesc.h differs from the one
4764 created by NT when setting ACE entries in printer
4765 descriptors. NT4 complains about the property being edited by a
4768 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4769 psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
4771 NULL, psa, &sd_size);
4775 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4779 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4781 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4782 (unsigned int)sd_size));
4787 /****************************************************************************
4788 Get a security desc for a printer.
4789 ****************************************************************************/
4791 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4797 if (strlen(printername) > 2 && (temp = strchr(printername + 2, '\\'))) {
4798 printername = temp + 1;
4801 /* Fetch security descriptor from tdb */
4803 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4805 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4806 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4808 DEBUG(4,("using default secdesc for %s\n", printername));
4810 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4814 /* Save default security descriptor for later */
4816 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4817 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4819 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4820 tdb_prs_store(tdb_printers, key, &ps);
4827 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4828 this security descriptor has been created when winbindd was
4829 down. Take ownership of security descriptor. */
4831 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4834 /* Change sd owner to workgroup administrator */
4836 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4837 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4838 SEC_DESC *psd = NULL;
4843 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4845 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type,
4847 (*secdesc_ctr)->sec->grp_sid,
4848 (*secdesc_ctr)->sec->sacl,
4849 (*secdesc_ctr)->sec->dacl,
4852 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4854 /* Swap with other one */
4856 *secdesc_ctr = new_secdesc_ctr;
4860 nt_printing_setsec(printername, *secdesc_ctr);
4864 if (DEBUGLEVEL >= 10) {
4865 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4868 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4869 printername, the_acl->num_aces));
4871 for (i = 0; i < the_acl->num_aces; i++) {
4874 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4876 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4877 the_acl->ace[i].type, the_acl->ace[i].flags,
4878 the_acl->ace[i].info.mask));
4888 1: level not implemented
4889 2: file doesn't exist
4890 3: can't allocate memory
4891 4: can't free memory
4892 5: non existant struct
4896 A printer and a printer driver are 2 different things.
4897 NT manages them separatelly, Samba does the same.
4898 Why ? Simply because it's easier and it makes sense !
4900 Now explanation: You have 3 printers behind your samba server,
4901 2 of them are the same make and model (laser A and B). But laser B
4902 has an 3000 sheet feeder and laser A doesn't such an option.
4903 Your third printer is an old dot-matrix model for the accounting :-).
4905 If the /usr/local/samba/lib directory (default dir), you will have
4906 5 files to describe all of this.
4908 3 files for the printers (1 by printer):
4911 NTprinter_accounting
4912 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4913 NTdriver_printer model X
4914 NTdriver_printer model Y
4916 jfm: I should use this comment for the text file to explain
4917 same thing for the forms BTW.
4918 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4922 /* Convert generic access rights to printer object specific access rights.
4923 It turns out that NT4 security descriptors use generic access rights and
4924 NT5 the object specific ones. */
4926 void map_printer_permissions(SEC_DESC *sd)
4930 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4931 se_map_generic(&sd->dacl->ace[i].info.mask,
4932 &printer_generic_mapping);
4936 /****************************************************************************
4937 Check a user has permissions to perform the given operation. We use the
4938 permission constants defined in include/rpc_spoolss.h to check the various
4939 actions we perform when checking printer access.
4941 PRINTER_ACCESS_ADMINISTER:
4942 print_queue_pause, print_queue_resume, update_printer_sec,
4943 update_printer, spoolss_addprinterex_level_2,
4944 _spoolss_setprinterdata
4949 JOB_ACCESS_ADMINISTER:
4950 print_job_delete, print_job_pause, print_job_resume,
4953 ****************************************************************************/
4954 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4956 SEC_DESC_BUF *secdesc = NULL;
4957 uint32 access_granted;
4961 TALLOC_CTX *mem_ctx = NULL;
4962 extern struct current_user current_user;
4964 /* If user is NULL then use the current_user structure */
4967 user = ¤t_user;
4969 /* Always allow root or printer admins to do anything */
4971 if (user->uid == 0 ||
4972 user_in_list(uidtoname(user->uid), lp_printer_admin(snum), user->groups, user->ngroups)) {
4976 /* Get printer name */
4978 pname = PRINTERNAME(snum);
4980 if (!pname || !*pname) {
4985 /* Get printer security descriptor */
4987 if(!(mem_ctx = talloc_init("print_access_check"))) {
4992 nt_printing_getsec(mem_ctx, pname, &secdesc);
4994 if (access_type == JOB_ACCESS_ADMINISTER) {
4995 SEC_DESC_BUF *parent_secdesc = secdesc;
4997 /* Create a child security descriptor to check permissions
4998 against. This is because print jobs are child objects
4999 objects of a printer. */
5001 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
5003 /* Now this is the bit that really confuses me. The access
5004 type needs to be changed from JOB_ACCESS_ADMINISTER to
5005 PRINTER_ACCESS_ADMINISTER for this to work. Something
5006 to do with the child (job) object becoming like a
5009 access_type = PRINTER_ACCESS_ADMINISTER;
5014 map_printer_permissions(secdesc->sec);
5016 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
5017 &access_granted, &status);
5019 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
5021 talloc_destroy(mem_ctx);
5029 /****************************************************************************
5030 Check the time parameters allow a print operation.
5031 *****************************************************************************/
5033 BOOL print_time_access_check(int snum)
5035 NT_PRINTER_INFO_LEVEL *printer = NULL;
5037 time_t now = time(NULL);
5041 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))))
5044 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
5048 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
5050 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
5053 free_a_printer(&printer, 2);