sync'ing up for 3.0alpha20 release
[Samba/gbeck.git] / source3 / printing / nt_printing.c
blob58eba9d87e8cd4ef014965b54c20c85222d4583b
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 extern DOM_SID global_sid_World;
27 static TDB_CONTEXT *tdb_forms; /* used for forms files */
28 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
29 static TDB_CONTEXT *tdb_printers; /* used for printers files */
31 #define FORMS_PREFIX "FORMS/"
32 #define DRIVERS_PREFIX "DRIVERS/"
33 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
34 #define PRINTERS_PREFIX "PRINTERS/"
35 #define SECDESC_PREFIX "SECDESC/"
36 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
38 #define NTDRIVERS_DATABASE_VERSION_1 1
39 #define NTDRIVERS_DATABASE_VERSION_2 2
40 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
42 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
44 /* Map generic permissions to printer object specific permissions */
46 GENERIC_MAPPING printer_generic_mapping = {
47 PRINTER_READ,
48 PRINTER_WRITE,
49 PRINTER_EXECUTE,
50 PRINTER_ALL_ACCESS
53 STANDARD_MAPPING printer_std_mapping = {
54 PRINTER_READ,
55 PRINTER_WRITE,
56 PRINTER_EXECUTE,
57 PRINTER_ALL_ACCESS
60 /* Map generic permissions to print server object specific permissions */
62 GENERIC_MAPPING printserver_generic_mapping = {
63 SERVER_READ,
64 SERVER_WRITE,
65 SERVER_EXECUTE,
66 SERVER_ALL_ACCESS
69 STANDARD_MAPPING printserver_std_mapping = {
70 SERVER_READ,
71 SERVER_WRITE,
72 SERVER_EXECUTE,
73 SERVER_ALL_ACCESS
76 /* We need one default form to support our default printer. Msoft adds the
77 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
78 array index). Letter is always first, so (for the current code) additions
79 always put things in the correct order. */
80 static nt_forms_struct default_forms[] = {
81 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
83 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
84 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
85 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
86 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
87 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
88 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
89 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
91 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
92 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
93 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
94 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
95 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
96 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
97 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
98 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
99 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
100 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
101 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
102 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
103 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
104 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
105 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
106 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
107 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
108 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
109 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
110 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
111 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
112 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
113 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
114 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
115 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
116 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
117 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
118 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
119 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
120 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
121 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
122 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
123 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
124 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
125 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
126 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
127 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
128 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
130 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
131 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
132 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
133 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
134 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
135 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
136 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
137 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
138 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
139 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
140 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
141 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
142 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
143 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
144 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
145 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
146 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
147 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
148 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
149 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
150 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
151 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
152 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
153 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
154 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
155 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
156 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
157 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
158 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
159 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
160 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
161 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
162 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
163 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
164 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
165 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
166 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
167 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
168 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
169 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
170 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
171 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
172 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
173 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
174 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
175 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
176 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
177 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
178 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
179 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
180 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
181 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
182 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
183 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
184 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
185 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
186 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
187 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
188 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
189 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
190 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
191 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
192 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
193 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
194 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
195 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
196 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
197 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
198 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
201 static BOOL upgrade_to_version_3(void)
203 TDB_DATA kbuf, newkey, dbuf;
205 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
207 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
208 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
210 dbuf = tdb_fetch(tdb_drivers, kbuf);
212 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
213 DEBUG(0,("upgrade_to_version_3:moving form\n"));
214 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
215 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
216 return False;
218 if (tdb_delete(tdb_drivers, kbuf) != 0) {
219 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
220 return False;
224 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
225 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
226 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
227 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
228 return False;
230 if (tdb_delete(tdb_drivers, kbuf) != 0) {
231 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
232 return False;
236 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
237 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
238 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
239 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
240 return False;
242 if (tdb_delete(tdb_drivers, kbuf) != 0) {
243 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
244 return False;
248 SAFE_FREE(dbuf.dptr);
251 return True;
254 /****************************************************************************
255 Open the NT printing tdb.
256 ****************************************************************************/
258 BOOL nt_printing_init(void)
260 static pid_t local_pid;
261 char *vstring = "INFO/version";
263 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
264 return True;
266 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
267 if (!tdb_drivers) {
268 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
269 lock_path("ntdrivers.tdb"), strerror(errno) ));
270 return False;
273 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
274 if (!tdb_printers) {
275 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
276 lock_path("ntprinters.tdb"), strerror(errno) ));
277 return False;
280 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
281 if (!tdb_forms) {
282 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
283 lock_path("ntforms.tdb"), strerror(errno) ));
284 return False;
287 local_pid = sys_getpid();
289 /* handle a Samba upgrade */
290 tdb_lock_bystring(tdb_drivers, vstring);
292 int32 vers_id;
294 /* Cope with byte-reversed older versions of the db. */
295 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
296 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
297 /* Written on a bigendian machine with old fetch_int code. Save as le. */
298 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
299 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
300 vers_id = NTDRIVERS_DATABASE_VERSION;
303 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
305 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
306 if (!upgrade_to_version_3())
307 return False;
308 } else
309 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
311 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
314 tdb_unlock_bystring(tdb_drivers, vstring);
316 update_c_setprinter(True);
319 * register callback to handle updating printers as new
320 * drivers are installed
323 message_register( MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer );
326 * register callback to handle updating printer data
327 * when a driver is initialized
330 message_register( MSG_PRINTERDATA_INIT_RESET, reset_all_printerdata );
333 return True;
336 /*******************************************************************
337 tdb traversal function for counting printers.
338 ********************************************************************/
340 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
341 TDB_DATA data, void *context)
343 int *printer_count = (int*)context;
345 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
346 (*printer_count)++;
347 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
350 return 0;
353 /*******************************************************************
354 Update the spooler global c_setprinter. This variable is initialized
355 when the parent smbd starts with the number of existing printers. It
356 is monotonically increased by the current number of printers *after*
357 each add or delete printer RPC. Only Microsoft knows why... JRR020119
358 ********************************************************************/
360 uint32 update_c_setprinter(BOOL initialize)
362 int32 c_setprinter;
363 int32 printer_count = 0;
365 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
367 /* Traverse the tdb, counting the printers */
368 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
370 /* If initializing, set c_setprinter to current printers count
371 * otherwise, bump it by the current printer count
373 if (!initialize)
374 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
375 else
376 c_setprinter = printer_count;
378 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
379 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
381 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
383 return (uint32)c_setprinter;
386 /*******************************************************************
387 Get the spooler global c_setprinter, accounting for initialization.
388 ********************************************************************/
390 uint32 get_c_setprinter(void)
392 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
394 if (c_setprinter == (int32)-1)
395 c_setprinter = update_c_setprinter(True);
397 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
399 return (uint32)c_setprinter;
402 /****************************************************************************
403 Get builtin form struct list.
404 ****************************************************************************/
406 int get_builtin_ntforms(nt_forms_struct **list)
408 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
409 return sizeof(default_forms) / sizeof(default_forms[0]);
412 /****************************************************************************
413 get a builtin form struct
414 ****************************************************************************/
416 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
418 int i,count;
419 fstring form_name;
420 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
421 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
422 count = sizeof(default_forms) / sizeof(default_forms[0]);
423 for (i=0;i<count;i++) {
424 if (strequal(form_name,default_forms[i].name)) {
425 DEBUGADD(6,("Found builtin form %s \n", form_name));
426 memcpy(form,&default_forms[i],sizeof(*form));
427 break;
431 return (i !=count);
434 /****************************************************************************
435 get a form struct list
436 ****************************************************************************/
437 int get_ntforms(nt_forms_struct **list)
439 TDB_DATA kbuf, newkey, dbuf;
440 nt_forms_struct *tl;
441 nt_forms_struct form;
442 int ret;
443 int i;
444 int n = 0;
446 for (kbuf = tdb_firstkey(tdb_forms);
447 kbuf.dptr;
448 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
450 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
451 continue;
453 dbuf = tdb_fetch(tdb_forms, kbuf);
454 if (!dbuf.dptr)
455 continue;
457 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
458 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
459 &i, &form.flag, &form.width, &form.length, &form.left,
460 &form.top, &form.right, &form.bottom);
461 SAFE_FREE(dbuf.dptr);
462 if (ret != dbuf.dsize)
463 continue;
465 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
466 if (!tl) {
467 DEBUG(0,("get_ntforms: Realloc fail.\n"));
468 return 0;
470 *list = tl;
471 (*list)[n] = form;
472 n++;
476 return n;
479 /****************************************************************************
480 write a form struct list
481 ****************************************************************************/
482 int write_ntforms(nt_forms_struct **list, int number)
484 pstring buf, key;
485 int len;
486 TDB_DATA kbuf,dbuf;
487 int i;
489 for (i=0;i<number;i++) {
490 /* save index, so list is rebuilt in correct order */
491 len = tdb_pack(buf, sizeof(buf), "dddddddd",
492 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
493 (*list)[i].left, (*list)[i].top, (*list)[i].right,
494 (*list)[i].bottom);
495 if (len > sizeof(buf)) break;
496 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
497 kbuf.dsize = strlen(key)+1;
498 kbuf.dptr = key;
499 dbuf.dsize = len;
500 dbuf.dptr = buf;
501 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
504 return i;
507 /****************************************************************************
508 add a form struct at the end of the list
509 ****************************************************************************/
510 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
512 int n=0;
513 BOOL update;
514 fstring form_name;
515 nt_forms_struct *tl;
518 * NT tries to add forms even when
519 * they are already in the base
520 * only update the values if already present
523 update=False;
525 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
526 for (n=0; n<*count; n++) {
527 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
528 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
529 update=True;
530 break;
534 if (update==False) {
535 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
536 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
537 return False;
539 *list = tl;
540 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
541 (*count)++;
544 (*list)[n].flag=form->flags;
545 (*list)[n].width=form->size_x;
546 (*list)[n].length=form->size_y;
547 (*list)[n].left=form->left;
548 (*list)[n].top=form->top;
549 (*list)[n].right=form->right;
550 (*list)[n].bottom=form->bottom;
552 return True;
555 /****************************************************************************
556 delete a named form struct
557 ****************************************************************************/
558 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
560 pstring key;
561 TDB_DATA kbuf;
562 int n=0;
563 fstring form_name;
565 *ret = WERR_OK;
567 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
569 for (n=0; n<*count; n++) {
570 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
571 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
572 break;
576 if (n == *count) {
577 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
578 *ret = WERR_INVALID_PARAM;
579 return False;
582 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
583 kbuf.dsize = strlen(key)+1;
584 kbuf.dptr = key;
585 if (tdb_delete(tdb_forms, kbuf) != 0) {
586 *ret = WERR_NOMEM;
587 return False;
590 return True;
593 /****************************************************************************
594 update a form struct
595 ****************************************************************************/
596 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
598 int n=0;
599 fstring form_name;
600 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
602 DEBUG(106, ("[%s]\n", form_name));
603 for (n=0; n<count; n++)
605 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
606 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
607 break;
610 if (n==count) return;
612 (*list)[n].flag=form->flags;
613 (*list)[n].width=form->size_x;
614 (*list)[n].length=form->size_y;
615 (*list)[n].left=form->left;
616 (*list)[n].top=form->top;
617 (*list)[n].right=form->right;
618 (*list)[n].bottom=form->bottom;
621 /****************************************************************************
622 get the nt drivers list
624 traverse the database and look-up the matching names
625 ****************************************************************************/
626 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
628 int total=0;
629 fstring short_archi;
630 fstring *fl;
631 pstring key;
632 TDB_DATA kbuf, newkey;
634 get_short_archi(short_archi, architecture);
635 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
637 for (kbuf = tdb_firstkey(tdb_drivers);
638 kbuf.dptr;
639 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
640 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
642 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
643 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
644 return -1;
646 else *list = fl;
648 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
649 total++;
652 return(total);
655 /****************************************************************************
656 function to do the mapping between the long architecture name and
657 the short one.
658 ****************************************************************************/
659 BOOL get_short_archi(char *short_archi, char *long_archi)
661 struct table {
662 char *long_archi;
663 char *short_archi;
666 struct table archi_table[]=
668 {"Windows 4.0", "WIN40" },
669 {"Windows NT x86", "W32X86" },
670 {"Windows NT R4000", "W32MIPS" },
671 {"Windows NT Alpha_AXP", "W32ALPHA" },
672 {"Windows NT PowerPC", "W32PPC" },
673 {NULL, "" }
676 int i=-1;
678 DEBUG(107,("Getting architecture dependant directory\n"));
679 do {
680 i++;
681 } while ( (archi_table[i].long_archi!=NULL ) &&
682 StrCaseCmp(long_archi, archi_table[i].long_archi) );
684 if (archi_table[i].long_archi==NULL) {
685 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
686 return False;
689 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
691 DEBUGADD(108,("index: [%d]\n", i));
692 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
693 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
695 return True;
698 /****************************************************************************
699 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
700 There are two case to be covered here: PE (Portable Executable) and NE (New
701 Executable) files. Both files support the same INFO structure, but PE files
702 store the signature in unicode, and NE files store it as !unicode.
703 returns -1 on error, 1 on version info found, and 0 on no version info found.
704 ****************************************************************************/
706 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
708 int i;
709 char *buf;
710 ssize_t byte_count;
712 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
713 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
714 fname, PE_HEADER_SIZE));
715 goto error_exit;
718 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
719 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
720 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
721 fname, byte_count));
722 goto no_version_info;
725 /* Is this really a DOS header? */
726 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
727 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
728 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
729 goto no_version_info;
732 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
733 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
734 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
735 fname, errno));
736 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
737 goto no_version_info;
740 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
741 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
742 fname, byte_count));
743 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
744 goto no_version_info;
747 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
748 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
749 int num_sections;
750 int section_table_bytes;
752 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
753 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
754 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
755 /* At this point, we assume the file is in error. It still could be somthing
756 * else besides a PE file, but it unlikely at this point.
758 goto error_exit;
761 /* get the section table */
762 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
763 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
764 SAFE_FREE(buf);
765 if ((buf=malloc(section_table_bytes)) == NULL) {
766 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
767 fname, section_table_bytes));
768 goto error_exit;
771 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
772 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
773 fname, byte_count));
774 goto error_exit;
777 /* Iterate the section table looking for the resource section ".rsrc" */
778 for (i = 0; i < num_sections; i++) {
779 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
781 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
782 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
783 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
785 SAFE_FREE(buf);
786 if ((buf=malloc(section_bytes)) == NULL) {
787 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
788 fname, section_bytes));
789 goto error_exit;
792 /* Seek to the start of the .rsrc section info */
793 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
794 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
795 fname, errno));
796 goto error_exit;
799 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
800 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
801 fname, byte_count));
802 goto error_exit;
805 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
806 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
807 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
808 /* Align to next long address */
809 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
811 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
812 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
813 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
815 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
816 fname, *major, *minor,
817 (*major>>16)&0xffff, *major&0xffff,
818 (*minor>>16)&0xffff, *minor&0xffff));
819 SAFE_FREE(buf);
820 return 1;
827 /* Version info not found, fall back to origin date/time */
828 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
829 SAFE_FREE(buf);
830 return 0;
832 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
833 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
834 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
835 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
836 /* At this point, we assume the file is in error. It still could be somthing
837 * else besides a NE file, but it unlikely at this point. */
838 goto error_exit;
841 /* Allocate a bit more space to speed up things */
842 SAFE_FREE(buf);
843 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
844 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
845 fname, PE_HEADER_SIZE));
846 goto error_exit;
849 /* This is a HACK! I got tired of trying to sort through the messy
850 * 'NE' file format. If anyone wants to clean this up please have at
851 * it, but this works. 'NE' files will eventually fade away. JRR */
852 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
853 /* Cover case that should not occur in a well formed 'NE' .dll file */
854 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
856 for(i=0; i<byte_count; i++) {
857 /* Fast skip past data that can't possibly match */
858 if (buf[i] != 'V') continue;
860 /* Potential match data crosses buf boundry, move it to beginning
861 * of buf, and fill the buf with as much as it will hold. */
862 if (i>byte_count-VS_VERSION_INFO_SIZE) {
863 int bc;
865 memcpy(buf, &buf[i], byte_count-i);
866 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
867 (byte_count-i))) < 0) {
869 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
870 fname, errno));
871 goto error_exit;
874 byte_count = bc + (byte_count - i);
875 if (byte_count<VS_VERSION_INFO_SIZE) break;
877 i = 0;
880 /* Check that the full signature string and the magic number that
881 * follows exist (not a perfect solution, but the chances that this
882 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
883 * twice, as it is simpler to read the code. */
884 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
885 /* Compute skip alignment to next long address */
886 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
887 sizeof(VS_SIGNATURE)) & 3;
888 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
890 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
891 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
892 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
893 fname, *major, *minor,
894 (*major>>16)&0xffff, *major&0xffff,
895 (*minor>>16)&0xffff, *minor&0xffff));
896 SAFE_FREE(buf);
897 return 1;
902 /* Version info not found, fall back to origin date/time */
903 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
904 SAFE_FREE(buf);
905 return 0;
907 } else
908 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
909 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
910 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
912 no_version_info:
913 SAFE_FREE(buf);
914 return 0;
916 error_exit:
917 SAFE_FREE(buf);
918 return -1;
921 /****************************************************************************
922 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
923 share one or more files. During the MS installation process files are checked
924 to insure that only a newer version of a shared file is installed over an
925 older version. There are several possibilities for this comparison. If there
926 is no previous version, the new one is newer (obviously). If either file is
927 missing the version info structure, compare the creation date (on Unix use
928 the modification date). Otherwise chose the numerically larger version number.
929 ****************************************************************************/
930 static int file_version_is_newer(connection_struct *conn, fstring new_file,
931 fstring old_file)
933 BOOL use_version = True;
934 pstring filepath;
936 uint32 new_major;
937 uint32 new_minor;
938 time_t new_create_time;
940 uint32 old_major;
941 uint32 old_minor;
942 time_t old_create_time;
944 int access_mode;
945 int action;
946 files_struct *fsp = NULL;
947 SMB_STRUCT_STAT st;
948 SMB_STRUCT_STAT stat_buf;
949 BOOL bad_path;
951 ZERO_STRUCT(st);
952 ZERO_STRUCT(stat_buf);
953 new_create_time = (time_t)0;
954 old_create_time = (time_t)0;
956 /* Get file version info (if available) for previous file (if it exists) */
957 pstrcpy(filepath, old_file);
959 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
961 fsp = open_file_shared(conn, filepath, &stat_buf,
962 SET_OPEN_MODE(DOS_OPEN_RDONLY),
963 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
964 0, 0, &access_mode, &action);
965 if (!fsp) {
966 /* Old file not found, so by definition new file is in fact newer */
967 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
968 filepath, errno));
969 return True;
971 } else {
972 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
973 if (ret == -1) goto error_exit;
975 if (!ret) {
976 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
977 old_file));
978 use_version = False;
979 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
980 old_create_time = st.st_mtime;
981 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
984 close_file(fsp, True);
986 /* Get file version info (if available) for new file */
987 pstrcpy(filepath, new_file);
988 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
990 fsp = open_file_shared(conn, filepath, &stat_buf,
991 SET_OPEN_MODE(DOS_OPEN_RDONLY),
992 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
993 0, 0, &access_mode, &action);
994 if (!fsp) {
995 /* New file not found, this shouldn't occur if the caller did its job */
996 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
997 filepath, errno));
998 goto error_exit;
1000 } else {
1001 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1002 if (ret == -1) goto error_exit;
1004 if (!ret) {
1005 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1006 new_file));
1007 use_version = False;
1008 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1009 new_create_time = st.st_mtime;
1010 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1013 close_file(fsp, True);
1015 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1016 /* Compare versions and choose the larger version number */
1017 if (new_major > old_major ||
1018 (new_major == old_major && new_minor > old_minor)) {
1020 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1021 return True;
1023 else {
1024 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1025 return False;
1028 } else {
1029 /* Compare modification time/dates and choose the newest time/date */
1030 if (new_create_time > old_create_time) {
1031 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1032 return True;
1034 else {
1035 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1036 return False;
1040 error_exit:
1041 if(fsp)
1042 close_file(fsp, True);
1043 return -1;
1046 /****************************************************************************
1047 Determine the correct cVersion associated with an architecture and driver
1048 ****************************************************************************/
1049 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1050 struct current_user *user, WERROR *perr)
1052 int cversion;
1053 int access_mode;
1054 int action;
1055 NTSTATUS nt_status;
1056 pstring driverpath;
1057 DATA_BLOB null_pw;
1058 files_struct *fsp = NULL;
1059 BOOL bad_path;
1060 SMB_STRUCT_STAT st;
1061 connection_struct *conn;
1063 ZERO_STRUCT(st);
1065 *perr = WERR_INVALID_PARAM;
1067 /* If architecture is Windows 95/98/ME, the version is always 0. */
1068 if (strcmp(architecture, "WIN40") == 0) {
1069 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1070 *perr = WERR_OK;
1071 return 0;
1075 * Connect to the print$ share under the same account as the user connected
1076 * to the rpc pipe. Note we must still be root to do this.
1079 /* Null password is ok - we are already an authenticated user... */
1080 null_pw = data_blob(NULL, 0);
1081 become_root();
1082 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1083 unbecome_root();
1085 if (conn == NULL) {
1086 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1087 *perr = ntstatus_to_werror(nt_status);
1088 return -1;
1091 /* We are temporarily becoming the connection user. */
1092 if (!become_user(conn, conn->vuid)) {
1093 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1094 *perr = WERR_ACCESS_DENIED;
1095 return -1;
1098 /* Open the driver file (Portable Executable format) and determine the
1099 * deriver the cversion. */
1100 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1102 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1104 fsp = open_file_shared(conn, driverpath, &st,
1105 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1106 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1107 0, 0, &access_mode, &action);
1108 if (!fsp) {
1109 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1110 driverpath, errno));
1111 *perr = WERR_ACCESS_DENIED;
1112 goto error_exit;
1114 else {
1115 uint32 major;
1116 uint32 minor;
1117 int ret = get_file_version(fsp, driverpath, &major, &minor);
1118 if (ret == -1) goto error_exit;
1120 if (!ret) {
1121 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1122 goto error_exit;
1126 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1127 * for more details. Version in this case is not just the version of the
1128 * file, but the version in the sense of kernal mode (2) vs. user mode
1129 * (3) drivers. Other bits of the version fields are the version info.
1130 * JRR 010716
1132 cversion = major & 0x0000ffff;
1133 switch (cversion) {
1134 case 2: /* WinNT drivers */
1135 case 3: /* Win2K drivers */
1136 break;
1138 default:
1139 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1140 driverpath, cversion));
1141 goto error_exit;
1144 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1145 driverpath, major, minor));
1148 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1149 driverpath, cversion));
1151 close_file(fsp, True);
1152 close_cnum(conn, user->vuid);
1153 unbecome_user();
1154 *perr = WERR_OK;
1155 return cversion;
1158 error_exit:
1160 if(fsp)
1161 close_file(fsp, True);
1163 close_cnum(conn, user->vuid);
1164 unbecome_user();
1165 return -1;
1168 /****************************************************************************
1169 ****************************************************************************/
1170 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1171 struct current_user *user)
1173 fstring architecture;
1174 fstring new_name;
1175 char *p;
1176 int i;
1177 WERROR err;
1179 /* clean up the driver name.
1180 * we can get .\driver.dll
1181 * or worse c:\windows\system\driver.dll !
1183 /* using an intermediate string to not have overlaping memcpy()'s */
1184 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1185 fstrcpy(new_name, p+1);
1186 fstrcpy(driver->driverpath, new_name);
1189 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1190 fstrcpy(new_name, p+1);
1191 fstrcpy(driver->datafile, new_name);
1194 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1195 fstrcpy(new_name, p+1);
1196 fstrcpy(driver->configfile, new_name);
1199 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1200 fstrcpy(new_name, p+1);
1201 fstrcpy(driver->helpfile, new_name);
1204 if (driver->dependentfiles) {
1205 for (i=0; *driver->dependentfiles[i]; i++) {
1206 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1207 fstrcpy(new_name, p+1);
1208 fstrcpy(driver->dependentfiles[i], new_name);
1213 get_short_archi(architecture, driver->environment);
1215 /* jfm:7/16/2000 the client always sends the cversion=0.
1216 * The server should check which version the driver is by reading
1217 * the PE header of driver->driverpath.
1219 * For Windows 95/98 the version is 0 (so the value sent is correct)
1220 * For Windows NT (the architecture doesn't matter)
1221 * NT 3.1: cversion=0
1222 * NT 3.5/3.51: cversion=1
1223 * NT 4: cversion=2
1224 * NT2K: cversion=3
1226 if ((driver->cversion = get_correct_cversion( architecture,
1227 driver->driverpath, user, &err)) == -1)
1228 return err;
1230 return WERR_OK;
1233 /****************************************************************************
1234 ****************************************************************************/
1235 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user)
1237 fstring architecture;
1238 fstring new_name;
1239 char *p;
1240 int i;
1241 WERROR err;
1243 /* clean up the driver name.
1244 * we can get .\driver.dll
1245 * or worse c:\windows\system\driver.dll !
1247 /* using an intermediate string to not have overlaping memcpy()'s */
1248 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1249 fstrcpy(new_name, p+1);
1250 fstrcpy(driver->driverpath, new_name);
1253 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1254 fstrcpy(new_name, p+1);
1255 fstrcpy(driver->datafile, new_name);
1258 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1259 fstrcpy(new_name, p+1);
1260 fstrcpy(driver->configfile, new_name);
1263 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1264 fstrcpy(new_name, p+1);
1265 fstrcpy(driver->helpfile, new_name);
1268 if (driver->dependentfiles) {
1269 for (i=0; *driver->dependentfiles[i]; i++) {
1270 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1271 fstrcpy(new_name, p+1);
1272 fstrcpy(driver->dependentfiles[i], new_name);
1277 get_short_archi(architecture, driver->environment);
1279 /* jfm:7/16/2000 the client always sends the cversion=0.
1280 * The server should check which version the driver is by reading
1281 * the PE header of driver->driverpath.
1283 * For Windows 95/98 the version is 0 (so the value sent is correct)
1284 * For Windows NT (the architecture doesn't matter)
1285 * NT 3.1: cversion=0
1286 * NT 3.5/3.51: cversion=1
1287 * NT 4: cversion=2
1288 * NT2K: cversion=3
1290 if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
1291 return err;
1293 return WERR_OK;
1296 /****************************************************************************
1297 ****************************************************************************/
1298 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1299 uint32 level, struct current_user *user)
1301 switch (level) {
1302 case 3:
1304 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1305 driver=driver_abstract.info_3;
1306 return clean_up_driver_struct_level_3(driver, user);
1308 case 6:
1310 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1311 driver=driver_abstract.info_6;
1312 return clean_up_driver_struct_level_6(driver, user);
1314 default:
1315 return WERR_INVALID_PARAM;
1319 /****************************************************************************
1320 This function sucks and should be replaced. JRA.
1321 ****************************************************************************/
1323 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1325 dst->cversion = src->version;
1327 fstrcpy( dst->name, src->name);
1328 fstrcpy( dst->environment, src->environment);
1329 fstrcpy( dst->driverpath, src->driverpath);
1330 fstrcpy( dst->datafile, src->datafile);
1331 fstrcpy( dst->configfile, src->configfile);
1332 fstrcpy( dst->helpfile, src->helpfile);
1333 fstrcpy( dst->monitorname, src->monitorname);
1334 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1335 dst->dependentfiles = src->dependentfiles;
1338 #if 0 /* Debugging function */
1340 static char* ffmt(unsigned char *c){
1341 int i;
1342 static char ffmt_str[17];
1344 for (i=0; i<16; i++) {
1345 if ((c[i] < ' ') || (c[i] > '~'))
1346 ffmt_str[i]='.';
1347 else
1348 ffmt_str[i]=c[i];
1350 ffmt_str[16]='\0';
1351 return ffmt_str;
1354 #endif
1356 /****************************************************************************
1357 ****************************************************************************/
1358 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1359 struct current_user *user, WERROR *perr)
1361 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1362 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1363 fstring architecture;
1364 pstring new_dir;
1365 pstring old_name;
1366 pstring new_name;
1367 DATA_BLOB null_pw;
1368 connection_struct *conn;
1369 NTSTATUS nt_status;
1370 pstring inbuf;
1371 pstring outbuf;
1372 int ver = 0;
1373 int i;
1375 memset(inbuf, '\0', sizeof(inbuf));
1376 memset(outbuf, '\0', sizeof(outbuf));
1377 *perr = WERR_OK;
1379 if (level==3)
1380 driver=driver_abstract.info_3;
1381 else if (level==6) {
1382 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1383 driver = &converted_driver;
1384 } else {
1385 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1386 return False;
1389 get_short_archi(architecture, driver->environment);
1392 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1393 * Note we must be root to do this.
1396 become_root();
1397 null_pw = data_blob(NULL, 0);
1398 conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
1399 unbecome_root();
1401 if (conn == NULL) {
1402 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1403 *perr = ntstatus_to_werror(nt_status);
1404 return False;
1408 * Save who we are - we are temporarily becoming the connection user.
1411 if (!become_user(conn, conn->vuid)) {
1412 DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
1413 return False;
1417 * make the directories version and version\driver_name
1418 * under the architecture directory.
1420 DEBUG(5,("Creating first directory\n"));
1421 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1422 mkdir_internal(conn, new_dir);
1424 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1425 * listed for this driver which has already been moved, skip it (note:
1426 * drivers may list the same file name several times. Then check if the
1427 * file already exists in archi\cversion\, if so, check that the version
1428 * info (or time stamps if version info is unavailable) is newer (or the
1429 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1430 * Otherwise, delete the file.
1432 * If a file is not moved to archi\cversion\ because of an error, all the
1433 * rest of the 'unmoved' driver files are removed from archi\. If one or
1434 * more of the driver's files was already moved to archi\cversion\, it
1435 * potentially leaves the driver in a partially updated state. Version
1436 * trauma will most likely occur if an client attempts to use any printer
1437 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1438 * done is appropriate... later JRR
1441 DEBUG(5,("Moving files now !\n"));
1443 if (driver->driverpath && strlen(driver->driverpath)) {
1444 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1445 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1446 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1447 NTSTATUS status;
1448 status = rename_internals(conn, new_name, old_name, True);
1449 if (!NT_STATUS_IS_OK(status)) {
1450 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1451 new_name, old_name));
1452 *perr = ntstatus_to_werror(status);
1453 unlink_internals(conn, 0, new_name);
1454 ver = -1;
1457 else
1458 unlink_internals(conn, 0, new_name);
1461 if (driver->datafile && strlen(driver->datafile)) {
1462 if (!strequal(driver->datafile, driver->driverpath)) {
1463 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1464 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1465 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1466 NTSTATUS status;
1467 status = rename_internals(conn, new_name, old_name, True);
1468 if (!NT_STATUS_IS_OK(status)) {
1469 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1470 new_name, old_name));
1471 *perr = ntstatus_to_werror(status);
1472 unlink_internals(conn, 0, new_name);
1473 ver = -1;
1476 else
1477 unlink_internals(conn, 0, new_name);
1481 if (driver->configfile && strlen(driver->configfile)) {
1482 if (!strequal(driver->configfile, driver->driverpath) &&
1483 !strequal(driver->configfile, driver->datafile)) {
1484 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1485 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1486 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1487 NTSTATUS status;
1488 status = rename_internals(conn, new_name, old_name, True);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1491 new_name, old_name));
1492 *perr = ntstatus_to_werror(status);
1493 unlink_internals(conn, 0, new_name);
1494 ver = -1;
1497 else
1498 unlink_internals(conn, 0, new_name);
1502 if (driver->helpfile && strlen(driver->helpfile)) {
1503 if (!strequal(driver->helpfile, driver->driverpath) &&
1504 !strequal(driver->helpfile, driver->datafile) &&
1505 !strequal(driver->helpfile, driver->configfile)) {
1506 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1507 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1508 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1509 NTSTATUS status;
1510 status = rename_internals(conn, new_name, old_name, True);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1513 new_name, old_name));
1514 *perr = ntstatus_to_werror(status);
1515 unlink_internals(conn, 0, new_name);
1516 ver = -1;
1519 else
1520 unlink_internals(conn, 0, new_name);
1524 if (driver->dependentfiles) {
1525 for (i=0; *driver->dependentfiles[i]; i++) {
1526 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1527 !strequal(driver->dependentfiles[i], driver->datafile) &&
1528 !strequal(driver->dependentfiles[i], driver->configfile) &&
1529 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1530 int j;
1531 for (j=0; j < i; j++) {
1532 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1533 goto NextDriver;
1537 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1538 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1539 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1540 NTSTATUS status;
1541 status = rename_internals(conn, new_name, old_name, True);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1544 new_name, old_name));
1545 *perr = ntstatus_to_werror(status);
1546 unlink_internals(conn, 0, new_name);
1547 ver = -1;
1550 else
1551 unlink_internals(conn, 0, new_name);
1553 NextDriver: ;
1557 close_cnum(conn, user->vuid);
1558 unbecome_user();
1560 return ver == -1 ? False : True;
1563 /****************************************************************************
1564 ****************************************************************************/
1565 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1567 int len, buflen;
1568 fstring architecture;
1569 pstring directory;
1570 pstring temp_name;
1571 pstring key;
1572 char *buf;
1573 int i, ret;
1574 TDB_DATA kbuf, dbuf;
1576 get_short_archi(architecture, driver->environment);
1578 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1579 * \\server is added in the rpc server layer.
1580 * It does make sense to NOT store the server's name in the printer TDB.
1583 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1585 /* .inf files do not always list a file for each of the four standard files.
1586 * Don't prepend a path to a null filename, or client claims:
1587 * "The server on which the printer resides does not have a suitable
1588 * <printer driver name> printer driver installed. Click OK if you
1589 * wish to install the driver on your local machine."
1591 if (strlen(driver->driverpath)) {
1592 fstrcpy(temp_name, driver->driverpath);
1593 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1596 if (strlen(driver->datafile)) {
1597 fstrcpy(temp_name, driver->datafile);
1598 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1601 if (strlen(driver->configfile)) {
1602 fstrcpy(temp_name, driver->configfile);
1603 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1606 if (strlen(driver->helpfile)) {
1607 fstrcpy(temp_name, driver->helpfile);
1608 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1611 if (driver->dependentfiles) {
1612 for (i=0; *driver->dependentfiles[i]; i++) {
1613 fstrcpy(temp_name, driver->dependentfiles[i]);
1614 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1618 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1620 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1622 buf = NULL;
1623 len = buflen = 0;
1625 again:
1626 len = 0;
1627 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1628 driver->cversion,
1629 driver->name,
1630 driver->environment,
1631 driver->driverpath,
1632 driver->datafile,
1633 driver->configfile,
1634 driver->helpfile,
1635 driver->monitorname,
1636 driver->defaultdatatype);
1638 if (driver->dependentfiles) {
1639 for (i=0; *driver->dependentfiles[i]; i++) {
1640 len += tdb_pack(buf+len, buflen-len, "f",
1641 driver->dependentfiles[i]);
1645 if (len != buflen) {
1646 char *tb;
1648 tb = (char *)Realloc(buf, len);
1649 if (!tb) {
1650 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1651 ret = -1;
1652 goto done;
1654 else buf = tb;
1655 buflen = len;
1656 goto again;
1660 kbuf.dptr = key;
1661 kbuf.dsize = strlen(key)+1;
1662 dbuf.dptr = buf;
1663 dbuf.dsize = len;
1665 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1667 done:
1668 if (ret)
1669 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1671 SAFE_FREE(buf);
1672 return ret;
1675 /****************************************************************************
1676 ****************************************************************************/
1677 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1679 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1681 ZERO_STRUCT(info3);
1682 info3.cversion = driver->version;
1683 fstrcpy(info3.name,driver->name);
1684 fstrcpy(info3.environment,driver->environment);
1685 fstrcpy(info3.driverpath,driver->driverpath);
1686 fstrcpy(info3.datafile,driver->datafile);
1687 fstrcpy(info3.configfile,driver->configfile);
1688 fstrcpy(info3.helpfile,driver->helpfile);
1689 fstrcpy(info3.monitorname,driver->monitorname);
1690 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1691 info3.dependentfiles = driver->dependentfiles;
1693 return add_a_printer_driver_3(&info3);
1697 /****************************************************************************
1698 ****************************************************************************/
1699 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
1701 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1703 ZERO_STRUCT(info);
1705 fstrcpy(info.name, driver);
1706 fstrcpy(info.defaultdatatype, "RAW");
1708 fstrcpy(info.driverpath, "");
1709 fstrcpy(info.datafile, "");
1710 fstrcpy(info.configfile, "");
1711 fstrcpy(info.helpfile, "");
1713 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1714 return WERR_NOMEM;
1716 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1717 fstrcpy(info.dependentfiles[0], "");
1719 *info_ptr = memdup(&info, sizeof(info));
1721 return WERR_OK;
1724 /****************************************************************************
1725 ****************************************************************************/
1726 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
1728 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1729 TDB_DATA kbuf, dbuf;
1730 fstring architecture;
1731 int len = 0;
1732 int i;
1733 pstring key;
1735 ZERO_STRUCT(driver);
1737 get_short_archi(architecture, arch);
1739 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
1741 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
1743 kbuf.dptr = key;
1744 kbuf.dsize = strlen(key)+1;
1746 dbuf = tdb_fetch(tdb_drivers, kbuf);
1747 if (!dbuf.dptr)
1748 return WERR_UNKNOWN_PRINTER_DRIVER;
1750 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1751 &driver.cversion,
1752 driver.name,
1753 driver.environment,
1754 driver.driverpath,
1755 driver.datafile,
1756 driver.configfile,
1757 driver.helpfile,
1758 driver.monitorname,
1759 driver.defaultdatatype);
1761 i=0;
1762 while (len < dbuf.dsize)
1764 fstring *tddfs;
1766 tddfs = (fstring *)Realloc(driver.dependentfiles,
1767 sizeof(fstring)*(i+2));
1768 if (tddfs == NULL) {
1769 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1770 break;
1772 else driver.dependentfiles = tddfs;
1774 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1775 &driver.dependentfiles[i]);
1776 i++;
1779 if (driver.dependentfiles != NULL)
1780 fstrcpy(driver.dependentfiles[i], "");
1782 SAFE_FREE(dbuf.dptr);
1784 if (len != dbuf.dsize)
1786 SAFE_FREE(driver.dependentfiles);
1788 return get_a_printer_driver_3_default(info_ptr, drivername, arch);
1791 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1793 return WERR_OK;
1796 /****************************************************************************
1797 ****************************************************************************/
1798 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1800 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1801 TDB_DATA kbuf;
1802 pstring key;
1803 int i;
1804 line[0] = '\0';
1806 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1807 DEBUG(10,("driver key: [%s]\n", key));
1809 kbuf.dptr = key;
1810 kbuf.dsize = strlen(key)+1;
1811 if (!tdb_exists(tdb_drivers, kbuf))
1812 return False;
1814 ZERO_STRUCT(info3);
1815 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1817 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1818 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1819 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1820 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1821 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1822 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1823 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1825 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1826 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1827 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1829 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1830 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1831 pstrcat(line, info3->driverpath);
1832 pstrcat(line, ":");
1833 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1834 pstrcat(line, info3->datafile);
1835 pstrcat(line, ":");
1836 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1837 pstrcat(line, info3->helpfile);
1838 pstrcat(line, ":");
1839 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1840 pstrcat(line, info3->monitorname);
1841 pstrcat(line, ":");
1842 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1843 pstrcat(line, ":");
1845 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1846 if (i)
1847 pstrcat(line, ","); /* don't end in a "," */
1848 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1849 pstrcat(line, info3->dependentfiles[i]);
1852 SAFE_FREE(info3);
1854 return True;
1857 /****************************************************************************
1858 Debugging function, dump at level 6 the struct in the logs.
1859 ****************************************************************************/
1861 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1863 uint32 result;
1864 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1865 int i;
1867 DEBUG(20,("Dumping printer driver at level [%d]\n", level));
1869 switch (level)
1871 case 3:
1873 if (driver.info_3 == NULL)
1874 result=5;
1875 else {
1876 info3=driver.info_3;
1878 DEBUGADD(20,("version:[%d]\n", info3->cversion));
1879 DEBUGADD(20,("name:[%s]\n", info3->name));
1880 DEBUGADD(20,("environment:[%s]\n", info3->environment));
1881 DEBUGADD(20,("driverpath:[%s]\n", info3->driverpath));
1882 DEBUGADD(20,("datafile:[%s]\n", info3->datafile));
1883 DEBUGADD(20,("configfile:[%s]\n", info3->configfile));
1884 DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
1885 DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
1886 DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1888 for (i=0; info3->dependentfiles &&
1889 *info3->dependentfiles[i]; i++) {
1890 DEBUGADD(20,("dependentfile:[%s]\n",
1891 info3->dependentfiles[i]));
1893 result=0;
1895 break;
1897 default:
1898 DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1899 result=1;
1900 break;
1903 return result;
1906 /****************************************************************************
1907 ****************************************************************************/
1908 int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1910 int len = 0;
1912 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1914 if (!nt_devmode) return len;
1916 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1917 nt_devmode->devicename,
1918 nt_devmode->formname,
1920 nt_devmode->specversion,
1921 nt_devmode->driverversion,
1922 nt_devmode->size,
1923 nt_devmode->driverextra,
1924 nt_devmode->orientation,
1925 nt_devmode->papersize,
1926 nt_devmode->paperlength,
1927 nt_devmode->paperwidth,
1928 nt_devmode->scale,
1929 nt_devmode->copies,
1930 nt_devmode->defaultsource,
1931 nt_devmode->printquality,
1932 nt_devmode->color,
1933 nt_devmode->duplex,
1934 nt_devmode->yresolution,
1935 nt_devmode->ttoption,
1936 nt_devmode->collate,
1937 nt_devmode->logpixels,
1939 nt_devmode->fields,
1940 nt_devmode->bitsperpel,
1941 nt_devmode->pelswidth,
1942 nt_devmode->pelsheight,
1943 nt_devmode->displayflags,
1944 nt_devmode->displayfrequency,
1945 nt_devmode->icmmethod,
1946 nt_devmode->icmintent,
1947 nt_devmode->mediatype,
1948 nt_devmode->dithertype,
1949 nt_devmode->reserved1,
1950 nt_devmode->reserved2,
1951 nt_devmode->panningwidth,
1952 nt_devmode->panningheight,
1953 nt_devmode->private);
1956 if (nt_devmode->private) {
1957 len += tdb_pack(buf+len, buflen-len, "B",
1958 nt_devmode->driverextra,
1959 nt_devmode->private);
1962 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1964 return len;
1967 /****************************************************************************
1968 Pack all values in all printer keys
1969 ***************************************************************************/
1971 static int pack_values(NT_PRINTER_DATA *data, char *buf, int buflen)
1973 int len = 0;
1974 int i, j;
1975 REGISTRY_VALUE *val;
1976 REGVAL_CTR *val_ctr;
1977 pstring path;
1978 int num_values;
1980 if ( !data )
1981 return 0;
1983 /* loop over all keys */
1985 for ( i=0; i<data->num_keys; i++ )
1987 val_ctr = &data->keys[i].values;
1988 num_values = regval_ctr_numvals( val_ctr );
1990 /* loop over all values */
1992 for ( j=0; j<num_values; j++ )
1994 /* pathname should be stored as <key>\<value> */
1996 val = regval_ctr_specific_value( val_ctr, j );
1997 pstrcpy( path, data->keys[i].name );
1998 pstrcat( path, "\\" );
1999 pstrcat( path, regval_name(val) );
2001 len += tdb_pack(buf+len, buflen-len, "pPdB",
2002 val,
2003 path,
2004 regval_type(val),
2005 regval_size(val),
2006 regval_data_p(val) );
2011 /* terminator */
2013 len += tdb_pack(buf+len, buflen-len, "p", NULL);
2015 return len;
2019 /****************************************************************************
2020 Delete a printer - this just deletes the printer info file, any open
2021 handles are not affected.
2022 ****************************************************************************/
2024 uint32 del_a_printer(char *sharename)
2026 pstring key;
2027 TDB_DATA kbuf;
2029 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2031 kbuf.dptr=key;
2032 kbuf.dsize=strlen(key)+1;
2034 tdb_delete(tdb_printers, kbuf);
2035 return 0;
2038 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2039 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
2040 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2041 /****************************************************************************
2042 ****************************************************************************/
2043 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2045 pstring key;
2046 char *buf;
2047 int buflen, len;
2048 WERROR ret;
2049 TDB_DATA kbuf, dbuf;
2052 * in addprinter: no servername and the printer is the name
2053 * in setprinter: servername is \\server
2054 * and printer is \\server\\printer
2056 * Samba manages only local printers.
2057 * we currently don't support things like path=\\other_server\printer
2060 if (info->servername[0]!='\0') {
2061 trim_string(info->printername, info->servername, NULL);
2062 trim_string(info->printername, "\\", NULL);
2063 info->servername[0]='\0';
2067 * JFM: one day I'll forget.
2068 * below that's info->portname because that's the SAMBA sharename
2069 * and I made NT 'thinks' it's the portname
2070 * the info->sharename is the thing you can name when you add a printer
2071 * that's the short-name when you create shared printer for 95/98
2072 * So I've made a limitation in SAMBA: you can only have 1 printer model
2073 * behind a SAMBA share.
2076 buf = NULL;
2077 buflen = 0;
2079 again:
2080 len = 0;
2081 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2082 info->attributes,
2083 info->priority,
2084 info->default_priority,
2085 info->starttime,
2086 info->untiltime,
2087 info->status,
2088 info->cjobs,
2089 info->averageppm,
2090 info->changeid,
2091 info->c_setprinter,
2092 info->setuptime,
2093 info->servername,
2094 info->printername,
2095 info->sharename,
2096 info->portname,
2097 info->drivername,
2098 info->comment,
2099 info->location,
2100 info->sepfile,
2101 info->printprocessor,
2102 info->datatype,
2103 info->parameters);
2105 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2107 len += pack_values( &info->data, buf+len, buflen-len );
2109 if (buflen != len) {
2110 char *tb;
2112 tb = (char *)Realloc(buf, len);
2113 if (!tb) {
2114 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2115 ret = WERR_NOMEM;
2116 goto done;
2118 else buf = tb;
2119 buflen = len;
2120 goto again;
2124 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2126 kbuf.dptr = key;
2127 kbuf.dsize = strlen(key)+1;
2128 dbuf.dptr = buf;
2129 dbuf.dsize = len;
2131 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2133 done:
2134 if (!W_ERROR_IS_OK(ret))
2135 DEBUG(8, ("error updating printer to tdb on disk\n"));
2137 SAFE_FREE(buf);
2139 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2140 info->sharename, info->drivername, info->portname, len));
2142 return ret;
2146 /****************************************************************************
2147 Malloc and return an NT devicemode.
2148 ****************************************************************************/
2150 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2153 char adevice[32];
2154 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2156 if (nt_devmode == NULL) {
2157 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2158 return NULL;
2161 ZERO_STRUCTP(nt_devmode);
2163 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2164 fstrcpy(nt_devmode->devicename, adevice);
2166 fstrcpy(nt_devmode->formname, "Letter");
2168 nt_devmode->specversion = 0x0401;
2169 nt_devmode->driverversion = 0x0400;
2170 nt_devmode->size = 0x00DC;
2171 nt_devmode->driverextra = 0x0000;
2172 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2173 DEFAULTSOURCE | COPIES | SCALE |
2174 PAPERSIZE | ORIENTATION;
2175 nt_devmode->orientation = 1;
2176 nt_devmode->papersize = PAPER_LETTER;
2177 nt_devmode->paperlength = 0;
2178 nt_devmode->paperwidth = 0;
2179 nt_devmode->scale = 0x64;
2180 nt_devmode->copies = 1;
2181 nt_devmode->defaultsource = BIN_FORMSOURCE;
2182 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2183 nt_devmode->color = COLOR_MONOCHROME;
2184 nt_devmode->duplex = DUP_SIMPLEX;
2185 nt_devmode->yresolution = 0;
2186 nt_devmode->ttoption = TT_SUBDEV;
2187 nt_devmode->collate = COLLATE_FALSE;
2188 nt_devmode->icmmethod = 0;
2189 nt_devmode->icmintent = 0;
2190 nt_devmode->mediatype = 0;
2191 nt_devmode->dithertype = 0;
2193 /* non utilisés par un driver d'imprimante */
2194 nt_devmode->logpixels = 0;
2195 nt_devmode->bitsperpel = 0;
2196 nt_devmode->pelswidth = 0;
2197 nt_devmode->pelsheight = 0;
2198 nt_devmode->displayflags = 0;
2199 nt_devmode->displayfrequency = 0;
2200 nt_devmode->reserved1 = 0;
2201 nt_devmode->reserved2 = 0;
2202 nt_devmode->panningwidth = 0;
2203 nt_devmode->panningheight = 0;
2205 nt_devmode->private = NULL;
2206 return nt_devmode;
2209 /****************************************************************************
2210 Deepcopy an NT devicemode.
2211 ****************************************************************************/
2213 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2215 NT_DEVICEMODE *new_nt_devicemode = NULL;
2217 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2218 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2219 return NULL;
2222 new_nt_devicemode->private = NULL;
2223 if (nt_devicemode->private != NULL) {
2224 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2225 SAFE_FREE(new_nt_devicemode);
2226 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2227 return NULL;
2231 return new_nt_devicemode;
2234 /****************************************************************************
2235 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2236 ****************************************************************************/
2238 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2240 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2242 if(nt_devmode == NULL)
2243 return;
2245 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2247 SAFE_FREE(nt_devmode->private);
2248 SAFE_FREE(*devmode_ptr);
2251 /****************************************************************************
2252 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2253 ****************************************************************************/
2254 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2256 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2257 NT_PRINTER_DATA *data;
2258 int i;
2260 if ( !info )
2261 return;
2263 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2265 free_nt_devicemode(&info->devmode);
2267 /* clean up all registry keys */
2269 data = &info->data;
2270 for ( i=0; i<data->num_keys; i++ )
2272 SAFE_FREE( data->keys[i].name );
2273 regval_ctr_destroy( &data->keys[i].values );
2275 SAFE_FREE( data->keys );
2277 /* finally the top level structure */
2279 SAFE_FREE( *info_ptr );
2283 /****************************************************************************
2284 ****************************************************************************/
2285 int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2287 int len = 0;
2288 int extra_len = 0;
2289 NT_DEVICEMODE devmode;
2291 ZERO_STRUCT(devmode);
2293 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2295 if (!*nt_devmode) return len;
2297 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2298 devmode.devicename,
2299 devmode.formname,
2301 &devmode.specversion,
2302 &devmode.driverversion,
2303 &devmode.size,
2304 &devmode.driverextra,
2305 &devmode.orientation,
2306 &devmode.papersize,
2307 &devmode.paperlength,
2308 &devmode.paperwidth,
2309 &devmode.scale,
2310 &devmode.copies,
2311 &devmode.defaultsource,
2312 &devmode.printquality,
2313 &devmode.color,
2314 &devmode.duplex,
2315 &devmode.yresolution,
2316 &devmode.ttoption,
2317 &devmode.collate,
2318 &devmode.logpixels,
2320 &devmode.fields,
2321 &devmode.bitsperpel,
2322 &devmode.pelswidth,
2323 &devmode.pelsheight,
2324 &devmode.displayflags,
2325 &devmode.displayfrequency,
2326 &devmode.icmmethod,
2327 &devmode.icmintent,
2328 &devmode.mediatype,
2329 &devmode.dithertype,
2330 &devmode.reserved1,
2331 &devmode.reserved2,
2332 &devmode.panningwidth,
2333 &devmode.panningheight,
2334 &devmode.private);
2336 if (devmode.private) {
2337 /* the len in tdb_unpack is an int value and
2338 * devmode.driverextra is only a short
2340 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2341 devmode.driverextra=(uint16)extra_len;
2343 /* check to catch an invalid TDB entry so we don't segfault */
2344 if (devmode.driverextra == 0) {
2345 devmode.private = NULL;
2349 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2351 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2352 if (devmode.private)
2353 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2355 return len;
2358 /****************************************************************************
2359 allocate and initialize a new slot in
2360 ***************************************************************************/
2362 static int add_new_printer_key( NT_PRINTER_DATA *data, char *name )
2364 NT_PRINTER_KEY *d;
2365 int key_index;
2367 if ( !data || !name )
2368 return -1;
2370 /* allocate another slot in the NT_PRINTER_KEY array */
2372 d = Realloc( data->keys, sizeof(NT_PRINTER_KEY)*(data->num_keys+1) );
2373 if ( d )
2374 data->keys = d;
2376 key_index = data->num_keys;
2378 /* initialze new key */
2380 data->num_keys++;
2381 data->keys[key_index].name = strdup( name );
2383 ZERO_STRUCTP( &data->keys[key_index].values );
2385 regval_ctr_init( &data->keys[key_index].values );
2387 DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
2389 return key_index;
2392 /****************************************************************************
2393 search for a registry key name in the existing printer data
2394 ***************************************************************************/
2396 int lookup_printerkey( NT_PRINTER_DATA *data, char *name )
2398 int key_index = -1;
2399 int i;
2401 if ( !data || !name )
2402 return -1;
2404 DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
2406 /* loop over all existing keys */
2408 for ( i=0; i<data->num_keys; i++ )
2410 if ( strequal(data->keys[i].name, name) ) {
2411 DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
2412 key_index = i;
2413 break;
2418 return key_index;
2421 /****************************************************************************
2422 ***************************************************************************/
2424 uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys )
2426 int i, j;
2427 int key_len;
2428 int num_subkeys = 0;
2429 char *p;
2430 fstring *ptr, *subkeys_ptr = NULL;
2431 fstring subkeyname;
2433 if ( !data )
2434 return 0;
2436 for ( i=0; i<data->num_keys; i++ )
2438 if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 )
2440 /* match sure it is a subkey and not the key itself */
2442 key_len = strlen( key );
2443 if ( strlen(data->keys[i].name) == key_len )
2444 continue;
2446 /* get subkey path */
2448 p = data->keys[i].name + key_len;
2449 if ( *p == '\\' )
2450 p++;
2451 fstrcpy( subkeyname, p );
2452 if ( (p = strchr( subkeyname, '\\' )) )
2453 *p = '\0';
2455 /* don't add a key more than once */
2457 for ( j=0; j<num_subkeys; j++ ) {
2458 if ( strequal( subkeys_ptr[j], subkeyname ) )
2459 break;
2462 if ( j != num_subkeys )
2463 continue;
2465 /* found a match, so allocate space and copy the name */
2467 if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
2468 DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
2469 num_subkeys+1));
2470 SAFE_FREE( subkeys );
2471 return 0;
2474 subkeys_ptr = ptr;
2475 fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
2476 num_subkeys++;
2481 /* tag of the end */
2483 fstrcpy( subkeys_ptr[num_subkeys], "" );
2485 *subkeys = subkeys_ptr;
2487 return num_subkeys;
2490 /****************************************************************************
2491 ***************************************************************************/
2493 WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key )
2495 NT_PRINTER_DATA *data;
2496 int i;
2497 int removed_keys = 0;
2498 int empty_slot;
2500 data = &p2->data;
2501 empty_slot = data->num_keys;
2503 if ( !key )
2504 return WERR_INVALID_PARAM;
2506 /* remove all keys */
2508 if ( !strlen(key) )
2510 for ( i=0; i<data->num_keys; i++ )
2512 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2513 data->keys[i].name));
2515 SAFE_FREE( data->keys[i].name );
2516 regval_ctr_destroy( &data->keys[i].values );
2519 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
2520 p2->printername ));
2522 SAFE_FREE( data->keys );
2523 ZERO_STRUCTP( data );
2525 return WERR_OK;
2528 /* remove a specific key (and all subkeys) */
2530 for ( i=0; i<data->num_keys; i++ )
2532 if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 )
2534 DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
2535 data->keys[i].name));
2537 SAFE_FREE( data->keys[i].name );
2538 regval_ctr_destroy( &data->keys[i].values );
2540 /* mark the slot as empty */
2542 ZERO_STRUCTP( &data->keys[i] );
2546 /* find the first empty slot */
2548 for ( i=0; i<data->num_keys; i++ ) {
2549 if ( !data->keys[i].name ) {
2550 empty_slot = i;
2551 removed_keys++;
2552 break;
2556 if ( i == data->num_keys )
2557 /* nothing was removed */
2558 return WERR_INVALID_PARAM;
2560 /* move everything down */
2562 for ( i=empty_slot+1; i<data->num_keys; i++ ) {
2563 if ( data->keys[i].name ) {
2564 memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
2565 ZERO_STRUCTP( &data->keys[i] );
2566 empty_slot++;
2567 removed_keys++;
2571 /* update count */
2573 data->num_keys -= removed_keys;
2575 /* sanity check to see if anything is left */
2577 if ( !data->num_keys )
2579 DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
2581 SAFE_FREE( data->keys );
2582 ZERO_STRUCTP( data );
2585 return WERR_OK;
2588 /****************************************************************************
2589 ***************************************************************************/
2591 WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2593 WERROR result = WERR_OK;
2594 int key_index;
2596 /* we must have names on non-zero length */
2598 if ( !key || !*key|| !value || !*value )
2599 return WERR_INVALID_NAME;
2601 /* find the printer key first */
2603 key_index = lookup_printerkey( &p2->data, key );
2604 if ( key_index == -1 )
2605 return WERR_OK;
2607 regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
2609 DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
2610 key, value ));
2612 return result;
2615 /****************************************************************************
2616 ***************************************************************************/
2618 WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value,
2619 uint32 type, uint8 *data, int real_len )
2621 WERROR result = WERR_OK;
2622 int key_index;
2624 /* we must have names on non-zero length */
2626 if ( !key || !*key|| !value || !*value )
2627 return WERR_INVALID_NAME;
2629 /* find the printer key first */
2631 key_index = lookup_printerkey( &p2->data, key );
2632 if ( key_index == -1 )
2633 key_index = add_new_printer_key( &p2->data, key );
2635 if ( key_index == -1 )
2636 return WERR_NOMEM;
2638 regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
2639 type, data, real_len );
2641 DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
2642 key, value, type, real_len ));
2644 return result;
2647 /****************************************************************************
2648 ***************************************************************************/
2650 REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value )
2652 int key_index;
2654 if ( (key_index = lookup_printerkey( &p2->data, key )) == -1 )
2655 return NULL;
2657 DEBUG(8,("get_printer_data: Attempting to lookup key => [%s], value => [%s]\n",
2658 key, value ));
2660 return regval_ctr_getvalue( &p2->data.keys[key_index].values, value );
2663 /****************************************************************************
2664 Unpack a list of registry values frem the TDB
2665 ***************************************************************************/
2667 static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
2669 int len = 0;
2670 uint32 type;
2671 pstring string, valuename, keyname;
2672 char *str;
2673 int size;
2674 uint8 *data_p;
2675 REGISTRY_VALUE *regval_p;
2676 int key_index;
2678 /* add the "PrinterDriverData" key first for performance reasons */
2680 add_new_printer_key( printer_data, SPOOL_PRINTERDATA_KEY );
2682 /* loop and unpack the rest of the registry values */
2684 while ( True )
2687 /* check to see if there are any more registry values */
2689 len += tdb_unpack(buf+len, buflen-len, "p", &regval_p);
2690 if ( !regval_p )
2691 break;
2693 /* unpack the next regval */
2695 len += tdb_unpack(buf+len, buflen-len, "fdB",
2696 string,
2697 &type,
2698 &size,
2699 &data_p);
2702 * break of the keyname from the value name.
2703 * Should only be one '\' in the string returned.
2706 str = strrchr( string, '\\');
2708 /* Put in "PrinterDriverData" is no key specified */
2710 if ( !str ) {
2711 pstrcpy( keyname, SPOOL_PRINTERDATA_KEY );
2712 pstrcpy( valuename, string );
2714 else {
2715 *str = '\0';
2716 pstrcpy( keyname, string );
2717 pstrcpy( valuename, str+1 );
2720 /* see if we need a new key */
2722 if ( (key_index=lookup_printerkey( printer_data, keyname )) == -1 )
2723 key_index = add_new_printer_key( printer_data, keyname );
2725 if ( key_index == -1 ) {
2726 DEBUG(0,("unpack_values: Failed to allocate a new key [%s]!\n",
2727 keyname));
2728 break;
2731 /* add the new value */
2733 regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
2735 DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
2738 return len;
2741 /****************************************************************************
2742 ***************************************************************************/
2744 static void map_to_os2_driver(fstring drivername)
2746 static BOOL initialised=False;
2747 static fstring last_from,last_to;
2748 char *mapfile = lp_os2_driver_map();
2749 char **lines = NULL;
2750 int numlines = 0;
2751 int i;
2753 if (!strlen(drivername))
2754 return;
2756 if (!*mapfile)
2757 return;
2759 if (!initialised) {
2760 *last_from = *last_to = 0;
2761 initialised = True;
2764 if (strequal(drivername,last_from)) {
2765 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2766 fstrcpy(drivername,last_to);
2767 return;
2770 lines = file_lines_load(mapfile, &numlines);
2771 if (numlines == 0) {
2772 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2773 return;
2776 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2778 for( i = 0; i < numlines; i++) {
2779 char *nt_name = lines[i];
2780 char *os2_name = strchr(nt_name,'=');
2782 if (!os2_name)
2783 continue;
2785 *os2_name++ = 0;
2787 while (isspace(*nt_name))
2788 nt_name++;
2790 if (!*nt_name || strchr("#;",*nt_name))
2791 continue;
2794 int l = strlen(nt_name);
2795 while (l && isspace(nt_name[l-1])) {
2796 nt_name[l-1] = 0;
2797 l--;
2801 while (isspace(*os2_name))
2802 os2_name++;
2805 int l = strlen(os2_name);
2806 while (l && isspace(os2_name[l-1])) {
2807 os2_name[l-1] = 0;
2808 l--;
2812 if (strequal(nt_name,drivername)) {
2813 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2814 fstrcpy(last_from,drivername);
2815 fstrcpy(last_to,os2_name);
2816 fstrcpy(drivername,os2_name);
2817 file_lines_free(lines);
2818 return;
2822 file_lines_free(lines);
2825 /****************************************************************************
2826 get a default printer info 2 struct
2827 ****************************************************************************/
2828 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2830 int snum;
2831 NT_PRINTER_INFO_LEVEL_2 info;
2833 ZERO_STRUCT(info);
2835 snum = lp_servicenumber(sharename);
2837 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2838 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2839 get_called_name(), sharename);
2840 fstrcpy(info.sharename, sharename);
2841 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2842 fstrcpy(info.drivername, lp_printerdriver(snum));
2844 /* by setting the driver name to an empty string, a local NT admin
2845 can now run the **local** APW to install a local printer driver
2846 for a Samba shared printer in 2.2. Without this, drivers **must** be
2847 installed on the Samba server for NT clients --jerry */
2848 #if 0 /* JERRY --do not uncomment-- */
2849 if (!*info.drivername)
2850 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2851 #endif
2854 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2856 pstrcpy(info.comment, "");
2857 fstrcpy(info.printprocessor, "winprint");
2858 fstrcpy(info.datatype, "RAW");
2860 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2862 info.starttime = 0; /* Minutes since 12:00am GMT */
2863 info.untiltime = 0; /* Minutes since 12:00am GMT */
2864 info.priority = 1;
2865 info.default_priority = 1;
2866 info.setuptime = (uint32)time(NULL);
2869 * I changed this as I think it is better to have a generic
2870 * DEVMODE than to crash Win2k explorer.exe --jerry
2871 * See the HP Deskjet 990c Win2k drivers for an example.
2873 * However the default devmode appears to cause problems
2874 * with the HP CLJ 8500 PCL driver. Hence the addition of
2875 * the "default devmode" parameter --jerry 22/01/2002
2878 if (lp_default_devmode(snum)) {
2879 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2880 goto fail;
2882 else {
2883 info.devmode = NULL;
2886 /* This will get the current RPC talloc context, but we should be
2887 passing this as a parameter... fixme... JRA ! */
2889 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2890 goto fail;
2892 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2893 if (! *info_ptr) {
2894 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2895 goto fail;
2898 return WERR_OK;
2900 fail:
2901 if (info.devmode)
2902 free_nt_devicemode(&info.devmode);
2903 return WERR_ACCESS_DENIED;
2906 /****************************************************************************
2907 ****************************************************************************/
2908 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2910 pstring key;
2911 NT_PRINTER_INFO_LEVEL_2 info;
2912 int len = 0;
2913 TDB_DATA kbuf, dbuf;
2914 fstring printername;
2916 ZERO_STRUCT(info);
2918 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2920 kbuf.dptr = key;
2921 kbuf.dsize = strlen(key)+1;
2923 dbuf = tdb_fetch(tdb_printers, kbuf);
2924 if (!dbuf.dptr)
2925 return get_a_printer_2_default(info_ptr, sharename);
2927 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2928 &info.attributes,
2929 &info.priority,
2930 &info.default_priority,
2931 &info.starttime,
2932 &info.untiltime,
2933 &info.status,
2934 &info.cjobs,
2935 &info.averageppm,
2936 &info.changeid,
2937 &info.c_setprinter,
2938 &info.setuptime,
2939 info.servername,
2940 info.printername,
2941 info.sharename,
2942 info.portname,
2943 info.drivername,
2944 info.comment,
2945 info.location,
2946 info.sepfile,
2947 info.printprocessor,
2948 info.datatype,
2949 info.parameters);
2951 /* Samba has to have shared raw drivers. */
2952 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2954 /* Restore the stripped strings. */
2955 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2956 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2957 info.printername);
2958 fstrcpy(info.printername, printername);
2960 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2963 * Some client drivers freak out if there is a NULL devmode
2964 * (probably the driver is not checking before accessing
2965 * the devmode pointer) --jerry
2967 * See comments in get_a_printer_2_default()
2970 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2972 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2973 printername));
2974 info.devmode = construct_nt_devicemode(printername);
2977 len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len );
2979 /* This will get the current RPC talloc context, but we should be
2980 passing this as a parameter... fixme... JRA ! */
2982 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2984 /* Fix for OS/2 drivers. */
2986 if (get_remote_arch() == RA_OS2)
2987 map_to_os2_driver(info.drivername);
2989 SAFE_FREE(dbuf.dptr);
2990 *info_ptr=memdup(&info, sizeof(info));
2992 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2993 sharename, info.printername, info.drivername));
2995 return WERR_OK;
2998 /****************************************************************************
2999 debugging function, dump at level 6 the struct in the logs
3000 ****************************************************************************/
3001 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3003 uint32 result;
3004 NT_PRINTER_INFO_LEVEL_2 *info2;
3006 DEBUG(106,("Dumping printer at level [%d]\n", level));
3008 switch (level)
3010 case 2:
3012 if (printer.info_2 == NULL)
3013 result=5;
3014 else
3016 info2=printer.info_2;
3018 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
3019 DEBUGADD(106,("priority:[%d]\n", info2->priority));
3020 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
3021 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
3022 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
3023 DEBUGADD(106,("status:[%d]\n", info2->status));
3024 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
3025 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
3026 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
3027 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
3028 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
3030 DEBUGADD(106,("servername:[%s]\n", info2->servername));
3031 DEBUGADD(106,("printername:[%s]\n", info2->printername));
3032 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
3033 DEBUGADD(106,("portname:[%s]\n", info2->portname));
3034 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
3035 DEBUGADD(106,("comment:[%s]\n", info2->comment));
3036 DEBUGADD(106,("location:[%s]\n", info2->location));
3037 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
3038 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
3039 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
3040 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
3041 result=0;
3043 break;
3045 default:
3046 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
3047 result=1;
3048 break;
3051 return result;
3054 /****************************************************************************
3055 Get the parameters we can substitute in an NT print job.
3056 ****************************************************************************/
3058 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
3060 NT_PRINTER_INFO_LEVEL *printer = NULL;
3062 **printername = **sharename = **portname = '\0';
3064 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
3065 return;
3067 fstrcpy(*printername, printer->info_2->printername);
3068 fstrcpy(*sharename, printer->info_2->sharename);
3069 fstrcpy(*portname, printer->info_2->portname);
3071 free_a_printer(&printer, 2);
3074 /****************************************************************************
3075 Update the changeid time.
3076 This is SO NASTY as some drivers need this to change, others need it
3077 static. This value will change every second, and I must hope that this
3078 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
3079 UTAH ! JRA.
3080 ****************************************************************************/
3082 static uint32 rev_changeid(void)
3084 struct timeval tv;
3086 get_process_uptime(&tv);
3088 #if 1 /* JERRY */
3089 /* Return changeid as msec since spooler restart */
3090 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3091 #else
3093 * This setting seems to work well but is too untested
3094 * to replace the above calculation. Left in for experiementation
3095 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
3097 return tv.tv_sec * 10 + tv.tv_usec / 100000;
3098 #endif
3102 * The function below are the high level ones.
3103 * only those ones must be called from the spoolss code.
3104 * JFM.
3107 /****************************************************************************
3108 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
3109 ****************************************************************************/
3111 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3113 WERROR result;
3115 dump_a_printer(printer, level);
3117 switch (level)
3119 case 2:
3122 * Update the changestamp. Emperical tests show that the
3123 * ChangeID is always updated,but c_setprinter is
3124 * global spooler variable (not per printer).
3127 /* ChangeID **must** be increasing over the lifetime
3128 of client's spoolss service in order for the
3129 client's cache to show updates */
3131 printer.info_2->changeid = rev_changeid();
3134 * Because one day someone will ask:
3135 * NT->NT An admin connection to a remote
3136 * printer show changes imeediately in
3137 * the properities dialog
3139 * A non-admin connection will only show the
3140 * changes after viewing the properites page
3141 * 2 times. Seems to be related to a
3142 * race condition in the client between the spooler
3143 * updating the local cache and the Explorer.exe GUI
3144 * actually displaying the properties.
3146 * This is fixed in Win2k. admin/non-admin
3147 * connections both display changes immediately.
3149 * 14/12/01 --jerry
3152 result=update_a_printer_2(printer.info_2);
3153 break;
3155 default:
3156 result=WERR_UNKNOWN_LEVEL;
3157 break;
3160 return result;
3163 /****************************************************************************
3164 Initialize printer devmode & data with previously saved driver init values.
3165 ****************************************************************************/
3167 static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
3169 int len = 0;
3170 pstring key;
3171 TDB_DATA kbuf, dbuf;
3172 NT_PRINTER_INFO_LEVEL_2 info;
3175 ZERO_STRUCT(info);
3178 * Delete any printer data 'values' already set. When called for driver
3179 * replace, there will generally be some, but during an add printer, there
3180 * should not be any (if there are delete them).
3183 delete_all_printer_data( info_ptr, "" );
3185 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
3187 kbuf.dptr = key;
3188 kbuf.dsize = strlen(key)+1;
3190 dbuf = tdb_fetch(tdb_drivers, kbuf);
3191 if (!dbuf.dptr) {
3193 * When changing to a driver that has no init info in the tdb, remove
3194 * the previous drivers init info and leave the new on blank.
3196 free_nt_devicemode(&info_ptr->devmode);
3197 return False;
3201 * Get the saved DEVMODE..
3204 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
3207 * The saved DEVMODE contains the devicename from the printer used during
3208 * the initialization save. Change it to reflect the new printer.
3211 if ( info.devmode ) {
3212 ZERO_STRUCT(info.devmode->devicename);
3213 fstrcpy(info.devmode->devicename, info_ptr->printername);
3217 * NT/2k does not change out the entire DeviceMode of a printer
3218 * when changing the driver. Only the driverextra, private, &
3219 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
3221 * Later examination revealed that Windows NT/2k does reset the
3222 * the printer's device mode, bit **only** when you change a
3223 * property of the device mode such as the page orientation.
3224 * --jerry
3228 /* Bind the saved DEVMODE to the new the printer */
3230 free_nt_devicemode(&info_ptr->devmode);
3231 info_ptr->devmode = info.devmode;
3233 DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
3234 info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
3236 /* Add the printer data 'values' to the new printer */
3238 len += unpack_values( &info_ptr->data, dbuf.dptr+len, dbuf.dsize-len );
3241 SAFE_FREE(dbuf.dptr);
3243 return True;
3246 /****************************************************************************
3247 Initialize printer devmode & data with previously saved driver init values.
3248 When a printer is created using AddPrinter, the drivername bound to the
3249 printer is used to lookup previously saved driver initialization info, which
3250 is bound to the new printer.
3251 ****************************************************************************/
3253 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
3255 BOOL result = False;
3257 switch (level)
3259 case 2:
3260 result = set_driver_init_2(printer->info_2);
3261 break;
3263 default:
3264 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3265 level));
3266 break;
3269 return result;
3272 /****************************************************************************
3273 Delete driver init data stored for a specified driver
3274 ****************************************************************************/
3276 BOOL del_driver_init(char *drivername)
3278 pstring key;
3279 TDB_DATA kbuf;
3281 if (!drivername || !*drivername) {
3282 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3283 return False;
3286 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3288 kbuf.dptr = key;
3289 kbuf.dsize = strlen(key)+1;
3291 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3293 return (tdb_delete(tdb_drivers, kbuf) == 0);
3296 /****************************************************************************
3297 Pack up the DEVMODE and values for a printer into a 'driver init' entry
3298 in the tdb. Note: this is different from the driver entry and the printer
3299 entry. There should be a single driver init entry for each driver regardless
3300 of whether it was installed from NT or 2K. Technically, they should be
3301 different, but they work out to the same struct.
3302 ****************************************************************************/
3304 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3306 pstring key;
3307 char *buf;
3308 int buflen, len, ret;
3309 TDB_DATA kbuf, dbuf;
3311 buf = NULL;
3312 buflen = 0;
3314 again:
3315 len = 0;
3316 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3318 len += pack_values( &info->data, buf+len, buflen-len );
3320 if (buflen != len) {
3321 char *tb;
3323 tb = (char *)Realloc(buf, len);
3324 if (!tb) {
3325 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3326 ret = -1;
3327 goto done;
3329 else buf = tb;
3330 buflen = len;
3331 goto again;
3334 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3336 kbuf.dptr = key;
3337 kbuf.dsize = strlen(key)+1;
3338 dbuf.dptr = buf;
3339 dbuf.dsize = len;
3341 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3343 done:
3344 if (ret == -1)
3345 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3347 SAFE_FREE(buf);
3349 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & values for driver [%s]\n",
3350 info->sharename, info->drivername));
3352 return ret;
3355 /****************************************************************************
3356 Update (i.e. save) the driver init info (DEVMODE and values) for a printer
3357 ****************************************************************************/
3359 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3361 uint32 result;
3363 dump_a_printer(printer, level);
3365 switch (level)
3367 case 2:
3369 result = update_driver_init_2(printer.info_2);
3370 break;
3372 default:
3373 result = 1;
3374 break;
3377 return result;
3380 /****************************************************************************
3381 Convert the printer data value, a REG_BINARY array, into an initialization
3382 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3383 got to keep the endians happy :).
3384 ****************************************************************************/
3386 static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
3388 BOOL result = False;
3389 prs_struct ps;
3390 DEVICEMODE devmode;
3392 ZERO_STRUCT(devmode);
3394 prs_init(&ps, 0, ctx, UNMARSHALL);
3395 ps.data_p = (char *)data;
3396 ps.buffer_size = data_len;
3398 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3399 result = convert_devicemode("", &devmode, &nt_devmode);
3400 else
3401 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3403 return result;
3406 /****************************************************************************
3407 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3409 1. Use the driver's config DLL to this UNC printername and:
3410 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3411 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3412 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3414 The last step triggers saving the "driver initialization" information for
3415 this printer into the tdb. Later, new printers that use this driver will
3416 have this initialization information bound to them. This simulates the
3417 driver initialization, as if it had run on the Samba server (as it would
3418 have done on NT).
3420 The Win32 client side code requirement sucks! But until we can run arbitrary
3421 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3423 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3424 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3425 about it and you will realize why. JRR 010720
3426 ****************************************************************************/
3428 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
3430 WERROR status = WERR_OK;
3431 TALLOC_CTX *ctx = NULL;
3432 NT_DEVICEMODE *nt_devmode = NULL;
3433 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3436 * When the DEVMODE is already set on the printer, don't try to unpack it.
3438 DEBUG(8,("save_driver_init_2: Enter...\n"));
3440 if ( !printer->info_2->devmode && data_len )
3443 * Set devmode on printer info, so entire printer initialization can be
3444 * saved to tdb.
3447 if ((ctx = talloc_init()) == NULL)
3448 return WERR_NOMEM;
3450 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3451 status = WERR_NOMEM;
3452 goto done;
3455 ZERO_STRUCTP(nt_devmode);
3458 * The DEVMODE is held in the 'data' component of the param in raw binary.
3459 * Convert it to to a devmode structure
3461 if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
3462 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3463 status = WERR_INVALID_PARAM;
3464 goto done;
3467 printer->info_2->devmode = nt_devmode;
3471 * Pack up and add (or update) the DEVMODE and any current printer data to
3472 * a 'driver init' element in the tdb
3476 if ( update_driver_init(*printer, 2) != 0 ) {
3477 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3478 status = WERR_NOMEM;
3479 goto done;
3483 * If driver initialization info was successfully saved, set the current
3484 * printer to match it. This allows initialization of the current printer
3485 * as well as the driver.
3487 status = mod_a_printer(*printer, 2);
3488 if (!W_ERROR_IS_OK(status)) {
3489 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3490 printer->info_2->printername));
3493 done:
3494 talloc_destroy(ctx);
3495 free_nt_devicemode( &nt_devmode );
3497 printer->info_2->devmode = tmp_devmode;
3499 return status;
3502 /****************************************************************************
3503 Update the driver init info (DEVMODE and specifics) for a printer
3504 ****************************************************************************/
3506 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
3508 WERROR status = WERR_OK;
3510 switch (level)
3512 case 2:
3514 status = save_driver_init_2( printer, data, data_len );
3515 break;
3517 default:
3518 status = WERR_UNKNOWN_LEVEL;
3519 break;
3522 return status;
3525 /****************************************************************************
3526 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3527 ****************************************************************************/
3529 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3531 WERROR result;
3532 NT_PRINTER_INFO_LEVEL *printer = NULL;
3534 *pp_printer = NULL;
3536 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3538 switch (level)
3540 case 2:
3542 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3543 DEBUG(0,("get_a_printer: malloc fail.\n"));
3544 return WERR_NOMEM;
3546 ZERO_STRUCTP(printer);
3547 result=get_a_printer_2(&printer->info_2, sharename);
3548 if (W_ERROR_IS_OK(result)) {
3549 dump_a_printer(*printer, level);
3550 *pp_printer = printer;
3551 } else {
3552 SAFE_FREE(printer);
3554 break;
3556 default:
3557 result=WERR_UNKNOWN_LEVEL;
3558 break;
3561 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3563 return result;
3566 /****************************************************************************
3567 Deletes a NT_PRINTER_INFO_LEVEL struct.
3568 ****************************************************************************/
3570 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3572 uint32 result;
3573 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3575 DEBUG(104,("freeing a printer at level [%d]\n", level));
3577 if (printer == NULL)
3578 return 0;
3580 switch (level)
3582 case 2:
3584 if (printer->info_2 != NULL)
3586 free_nt_printer_info_level_2(&printer->info_2);
3587 result=0;
3589 else
3591 result=4;
3593 break;
3595 default:
3596 result=1;
3597 break;
3600 SAFE_FREE(*pp_printer);
3601 return result;
3604 /****************************************************************************
3605 ****************************************************************************/
3606 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3608 uint32 result;
3609 DEBUG(104,("adding a printer at level [%d]\n", level));
3610 dump_a_printer_driver(driver, level);
3612 switch (level)
3614 case 3:
3616 result=add_a_printer_driver_3(driver.info_3);
3617 break;
3620 case 6:
3622 result=add_a_printer_driver_6(driver.info_6);
3623 break;
3625 default:
3626 result=1;
3627 break;
3630 return result;
3632 /****************************************************************************
3633 ****************************************************************************/
3634 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3635 fstring drivername, fstring architecture, uint32 version)
3637 WERROR result;
3639 switch (level)
3641 case 3:
3642 /* Sometime we just want any version of the driver */
3644 if ( version == DRIVER_ANY_VERSION ) {
3645 /* look for Win2k first and then for NT4 */
3646 result = get_a_printer_driver_3(&driver->info_3, drivername,
3647 architecture, 3);
3649 if ( !W_ERROR_IS_OK(result) ) {
3650 result = get_a_printer_driver_3( &driver->info_3,
3651 drivername, architecture, 2 );
3654 else {
3655 result = get_a_printer_driver_3(&driver->info_3, drivername,
3656 architecture, version);
3658 break;
3660 default:
3661 result=W_ERROR(1);
3662 break;
3665 if (W_ERROR_IS_OK(result))
3666 dump_a_printer_driver(*driver, level);
3668 return result;
3671 /****************************************************************************
3672 ****************************************************************************/
3673 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3675 uint32 result;
3677 switch (level)
3679 case 3:
3681 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3682 if (driver.info_3 != NULL)
3684 info3=driver.info_3;
3685 SAFE_FREE(info3->dependentfiles);
3686 ZERO_STRUCTP(info3);
3687 SAFE_FREE(info3);
3688 result=0;
3690 else
3692 result=4;
3694 break;
3696 case 6:
3698 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3699 if (driver.info_6 != NULL)
3701 info6=driver.info_6;
3702 SAFE_FREE(info6->dependentfiles);
3703 SAFE_FREE(info6->previousnames);
3704 ZERO_STRUCTP(info6);
3705 SAFE_FREE(info6);
3706 result=0;
3708 else
3710 result=4;
3712 break;
3714 default:
3715 result=1;
3716 break;
3718 return result;
3722 /****************************************************************************
3723 Determine whether or not a particular driver is currently assigned
3724 to a printer
3725 ****************************************************************************/
3727 BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
3729 int snum;
3730 int n_services = lp_numservices();
3731 NT_PRINTER_INFO_LEVEL *printer = NULL;
3733 if ( !info_3 )
3734 return False;
3736 DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
3738 /* loop through the printers.tdb and check for the drivername */
3740 for (snum=0; snum<n_services; snum++)
3742 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
3743 continue;
3745 if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
3746 continue;
3748 if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
3749 free_a_printer( &printer, 2 );
3750 return True;
3753 free_a_printer( &printer, 2 );
3756 DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
3758 /* report that the driver is not in use by default */
3760 return False;
3764 /**********************************************************************
3765 Check to see if a ogiven file is in use by *info
3766 *********************************************************************/
3768 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3770 int i = 0;
3772 if ( !info )
3773 return False;
3775 if ( strequal(file, info->driverpath) )
3776 return True;
3778 if ( strequal(file, info->datafile) )
3779 return True;
3781 if ( strequal(file, info->configfile) )
3782 return True;
3784 if ( strequal(file, info->helpfile) )
3785 return True;
3787 /* see of there are any dependent files to examine */
3789 if ( !info->dependentfiles )
3790 return False;
3792 while ( *info->dependentfiles[i] )
3794 if ( strequal(file, info->dependentfiles[i]) )
3795 return True;
3797 i++;
3800 return False;
3804 /**********************************************************************
3805 Utility function to remove the dependent file pointed to by the
3806 input parameter from the list
3807 *********************************************************************/
3809 static void trim_dependent_file( fstring files[], int idx )
3812 /* bump everything down a slot */
3814 while( *files[idx+1] )
3816 fstrcpy( files[idx], files[idx+1] );
3817 idx++;
3820 *files[idx] = '\0';
3822 return;
3825 /**********************************************************************
3826 Check if any of the files used by src are also used by drv
3827 *********************************************************************/
3829 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
3830 NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
3832 BOOL in_use = False;
3833 int i = 0;
3835 if ( !src || !drv )
3836 return False;
3838 /* check each file. Remove it from the src structure if it overlaps */
3840 if ( drv_file_in_use(src->driverpath, drv) ) {
3841 in_use = True;
3842 DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
3843 fstrcpy( src->driverpath, "" );
3846 if ( drv_file_in_use(src->datafile, drv) ) {
3847 in_use = True;
3848 DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
3849 fstrcpy( src->datafile, "" );
3852 if ( drv_file_in_use(src->configfile, drv) ) {
3853 in_use = True;
3854 DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
3855 fstrcpy( src->configfile, "" );
3858 if ( drv_file_in_use(src->helpfile, drv) ) {
3859 in_use = True;
3860 DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
3861 fstrcpy( src->helpfile, "" );
3864 /* are there any dependentfiles to examine? */
3866 if ( !src->dependentfiles )
3867 return in_use;
3869 while ( *src->dependentfiles[i] )
3871 if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
3872 in_use = True;
3873 DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
3874 trim_dependent_file( src->dependentfiles, i );
3876 else
3877 i++;
3880 return in_use;
3883 /****************************************************************************
3884 Determine whether or not a particular driver files are currently being
3885 used by any other driver.
3887 Return value is True if any files were in use by other drivers
3888 and False otherwise.
3890 Upon return, *info has been modified to only contain the driver files
3891 which are not in use
3892 ****************************************************************************/
3894 BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
3896 int i;
3897 int ndrivers;
3898 uint32 version;
3899 fstring *list = NULL;
3900 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3902 if ( !info )
3903 return False;
3905 version = info->cversion;
3907 /* loop over all driver versions */
3909 DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
3911 /* get the list of drivers */
3913 list = NULL;
3914 ndrivers = get_ntdrivers(&list, info->environment, version);
3916 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
3917 ndrivers, info->environment, version));
3919 /* check each driver for overlap in files */
3921 for (i=0; i<ndrivers; i++)
3923 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3925 ZERO_STRUCT(driver);
3927 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i],
3928 info->environment, version)) )
3930 SAFE_FREE(list);
3931 return True;
3934 /* check if d2 uses any files from d1 */
3935 /* only if this is a different driver than the one being deleted */
3937 if ( !strequal(info->name, driver.info_3->name) )
3939 if ( trim_overlap_drv_files(info, driver.info_3) ) {
3940 free_a_printer_driver(driver, 3);
3941 SAFE_FREE( list );
3942 return True;
3946 free_a_printer_driver(driver, 3);
3949 SAFE_FREE(list);
3951 DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
3953 driver.info_3 = info;
3955 if ( DEBUGLEVEL >= 20 )
3956 dump_a_printer_driver( driver, 3 );
3958 return False;
3961 /****************************************************************************
3962 Actually delete the driver files. Make sure that
3963 printer_driver_files_in_use() return False before calling
3964 this.
3965 ****************************************************************************/
3967 static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
3969 int i = 0;
3970 char *s;
3971 connection_struct *conn;
3972 DATA_BLOB null_pw;
3973 NTSTATUS nt_status;
3975 if ( !info_3 )
3976 return False;
3978 DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
3981 * Connect to the print$ share under the same account as the
3982 * user connected to the rpc pipe. Note we must be root to
3983 * do this.
3986 become_root();
3987 null_pw = data_blob( NULL, 0 );
3988 conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
3989 unbecome_root();
3991 if ( !conn ) {
3992 DEBUG(0,("delete_driver_files: Unable to connect\n"));
3993 return False;
3996 /* Save who we are - we are temporarily becoming the connection user. */
3998 if ( !become_user(conn, conn->vuid) ) {
3999 DEBUG(0,("delete_driver_files: Can't become user!\n"));
4000 return False;
4003 /* now delete the files; must strip the '\print$' string from
4004 fron of path */
4006 if ( *info_3->driverpath ) {
4007 if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
4008 DEBUG(10,("deleting driverfile [%s]\n", s));
4009 unlink_internals(conn, 0, s);
4013 if ( *info_3->configfile ) {
4014 if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
4015 DEBUG(10,("deleting configfile [%s]\n", s));
4016 unlink_internals(conn, 0, s);
4020 if ( *info_3->datafile ) {
4021 if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
4022 DEBUG(10,("deleting datafile [%s]\n", s));
4023 unlink_internals(conn, 0, s);
4027 if ( *info_3->helpfile ) {
4028 if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
4029 DEBUG(10,("deleting helpfile [%s]\n", s));
4030 unlink_internals(conn, 0, s);
4034 /* check if we are done removing files */
4036 if ( info_3->dependentfiles )
4038 while ( *info_3->dependentfiles[i] ) {
4039 char *file;
4041 /* bypass the "\print$" portion of the path */
4043 if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL )
4045 DEBUG(10,("deleting dependent file [%s]\n", file));
4046 unlink_internals(conn, 0, file );
4049 i++;
4053 unbecome_user();
4055 return True;
4058 /****************************************************************************
4059 Remove a printer driver from the TDB. This assumes that the the driver was
4060 previously looked up.
4061 ***************************************************************************/
4063 WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
4064 uint32 version, BOOL delete_files )
4066 pstring key;
4067 fstring arch;
4068 TDB_DATA kbuf, dbuf;
4069 NT_PRINTER_DRIVER_INFO_LEVEL ctr;
4071 /* delete the tdb data first */
4073 get_short_archi(arch, info_3->environment);
4074 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
4075 arch, version, info_3->name);
4077 DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
4078 key, delete_files ? "TRUE" : "FALSE" ));
4080 ctr.info_3 = info_3;
4081 dump_a_printer_driver( ctr, 3 );
4083 kbuf.dptr=key;
4084 kbuf.dsize=strlen(key)+1;
4086 /* check if the driver actually exists for this environment */
4088 dbuf = tdb_fetch( tdb_drivers, kbuf );
4089 if ( !dbuf.dptr ) {
4090 DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
4091 return WERR_UNKNOWN_PRINTER_DRIVER;
4094 SAFE_FREE( dbuf.dptr );
4096 /* ok... the driver exists so the delete should return success */
4098 if (tdb_delete(tdb_drivers, kbuf) == -1) {
4099 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
4100 return WERR_ACCESS_DENIED;
4104 * now delete any associated files if delete_files == True
4105 * even if this part failes, we return succes because the
4106 * driver doesn not exist any more
4109 if ( delete_files )
4110 delete_driver_files( info_3, user );
4113 DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
4115 return WERR_OK;
4118 /****************************************************************************
4119 Store a security desc for a printer.
4120 ****************************************************************************/
4122 WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
4124 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4125 SEC_DESC_BUF *old_secdesc_ctr = NULL;
4126 prs_struct ps;
4127 TALLOC_CTX *mem_ctx = NULL;
4128 fstring key;
4129 WERROR status;
4131 mem_ctx = talloc_init();
4132 if (mem_ctx == NULL)
4133 return WERR_NOMEM;
4135 /* The old owner and group sids of the security descriptor are not
4136 present when new ACEs are added or removed by changing printer
4137 permissions through NT. If they are NULL in the new security
4138 descriptor then copy them over from the old one. */
4140 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
4141 DOM_SID *owner_sid, *group_sid;
4142 SEC_ACL *dacl, *sacl;
4143 SEC_DESC *psd = NULL;
4144 size_t size;
4146 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
4148 /* Pick out correct owner and group sids */
4150 owner_sid = secdesc_ctr->sec->owner_sid ?
4151 secdesc_ctr->sec->owner_sid :
4152 old_secdesc_ctr->sec->owner_sid;
4154 group_sid = secdesc_ctr->sec->grp_sid ?
4155 secdesc_ctr->sec->grp_sid :
4156 old_secdesc_ctr->sec->grp_sid;
4158 dacl = secdesc_ctr->sec->dacl ?
4159 secdesc_ctr->sec->dacl :
4160 old_secdesc_ctr->sec->dacl;
4162 sacl = secdesc_ctr->sec->sacl ?
4163 secdesc_ctr->sec->sacl :
4164 old_secdesc_ctr->sec->sacl;
4166 /* Make a deep copy of the security descriptor */
4168 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
4169 owner_sid, group_sid,
4170 sacl,
4171 dacl,
4172 &size);
4174 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
4177 if (!new_secdesc_ctr) {
4178 new_secdesc_ctr = secdesc_ctr;
4181 /* Store the security descriptor in a tdb */
4183 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
4184 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
4186 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
4187 &ps, 1)) {
4188 status = WERR_BADFUNC;
4189 goto out;
4192 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4194 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
4195 status = WERR_OK;
4196 } else {
4197 DEBUG(1,("Failed to store secdesc for %s\n", printername));
4198 status = WERR_BADFUNC;
4201 /* Free malloc'ed memory */
4203 out:
4205 prs_mem_free(&ps);
4206 if (mem_ctx)
4207 talloc_destroy(mem_ctx);
4208 return status;
4211 /****************************************************************************
4212 Construct a default security descriptor buffer for a printer.
4213 ****************************************************************************/
4215 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
4217 SEC_ACE ace[3];
4218 SEC_ACCESS sa;
4219 SEC_ACL *psa = NULL;
4220 SEC_DESC_BUF *sdb = NULL;
4221 SEC_DESC *psd = NULL;
4222 DOM_SID owner_sid;
4223 size_t sd_size;
4225 /* Create an ACE where Everyone is allowed to print */
4227 init_sec_access(&sa, PRINTER_ACE_PRINT);
4228 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
4229 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4231 /* Make the security descriptor owned by the Administrators group
4232 on the PDC of the domain. */
4234 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4235 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4236 } else {
4238 /* Backup plan - make printer owned by admins.
4239 This should emulate a lanman printer as security
4240 settings can't be changed. */
4242 sid_copy(&owner_sid, get_global_sam_sid());
4243 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4246 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4247 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4248 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
4249 SEC_ACE_FLAG_INHERIT_ONLY);
4251 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
4252 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
4253 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
4255 /* The ACL revision number in rpc_secdesc.h differs from the one
4256 created by NT when setting ACE entries in printer
4257 descriptors. NT4 complains about the property being edited by a
4258 NT5 machine. */
4260 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
4261 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
4262 &owner_sid, NULL,
4263 NULL, psa, &sd_size);
4266 if (!psd) {
4267 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
4268 return NULL;
4271 sdb = make_sec_desc_buf(ctx, sd_size, psd);
4273 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
4274 (unsigned int)sd_size));
4276 return sdb;
4279 /****************************************************************************
4280 Get a security desc for a printer.
4281 ****************************************************************************/
4283 BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
4285 prs_struct ps;
4286 fstring key;
4287 char *temp;
4289 if ((temp = strchr(printername + 2, '\\'))) {
4290 printername = temp + 1;
4293 /* Fetch security descriptor from tdb */
4295 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
4297 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
4298 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
4300 DEBUG(4,("using default secdesc for %s\n", printername));
4302 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
4303 return False;
4306 /* Save default security descriptor for later */
4308 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
4309 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
4311 if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
4312 tdb_prs_store(tdb_printers, key, &ps);
4314 prs_mem_free(&ps);
4316 return True;
4319 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
4320 this security descriptor has been created when winbindd was
4321 down. Take ownership of security descriptor. */
4323 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
4324 DOM_SID owner_sid;
4326 /* Change sd owner to workgroup administrator */
4328 if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
4329 SEC_DESC_BUF *new_secdesc_ctr = NULL;
4330 SEC_DESC *psd = NULL;
4331 size_t size;
4333 /* Create new sd */
4335 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
4337 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
4338 &owner_sid,
4339 (*secdesc_ctr)->sec->grp_sid,
4340 (*secdesc_ctr)->sec->sacl,
4341 (*secdesc_ctr)->sec->dacl,
4342 &size);
4344 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
4346 /* Swap with other one */
4348 *secdesc_ctr = new_secdesc_ctr;
4350 /* Set it */
4352 nt_printing_setsec(printername, *secdesc_ctr);
4356 if (DEBUGLEVEL >= 10) {
4357 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
4358 int i;
4360 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4361 printername, the_acl->num_aces));
4363 for (i = 0; i < the_acl->num_aces; i++) {
4364 fstring sid_str;
4366 sid_to_string(sid_str, &the_acl->ace[i].trustee);
4368 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
4369 the_acl->ace[i].type, the_acl->ace[i].flags,
4370 the_acl->ace[i].info.mask));
4374 prs_mem_free(&ps);
4375 return True;
4378 /* error code:
4379 0: everything OK
4380 1: level not implemented
4381 2: file doesn't exist
4382 3: can't allocate memory
4383 4: can't free memory
4384 5: non existant struct
4388 A printer and a printer driver are 2 different things.
4389 NT manages them separatelly, Samba does the same.
4390 Why ? Simply because it's easier and it makes sense !
4392 Now explanation: You have 3 printers behind your samba server,
4393 2 of them are the same make and model (laser A and B). But laser B
4394 has an 3000 sheet feeder and laser A doesn't such an option.
4395 Your third printer is an old dot-matrix model for the accounting :-).
4397 If the /usr/local/samba/lib directory (default dir), you will have
4398 5 files to describe all of this.
4400 3 files for the printers (1 by printer):
4401 NTprinter_laser A
4402 NTprinter_laser B
4403 NTprinter_accounting
4404 2 files for the drivers (1 for the laser and 1 for the dot matrix)
4405 NTdriver_printer model X
4406 NTdriver_printer model Y
4408 jfm: I should use this comment for the text file to explain
4409 same thing for the forms BTW.
4410 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
4414 /* Convert generic access rights to printer object specific access rights.
4415 It turns out that NT4 security descriptors use generic access rights and
4416 NT5 the object specific ones. */
4418 void map_printer_permissions(SEC_DESC *sd)
4420 int i;
4422 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
4423 se_map_generic(&sd->dacl->ace[i].info.mask,
4424 &printer_generic_mapping);
4428 /****************************************************************************
4429 Check a user has permissions to perform the given operation. We use the
4430 permission constants defined in include/rpc_spoolss.h to check the various
4431 actions we perform when checking printer access.
4433 PRINTER_ACCESS_ADMINISTER:
4434 print_queue_pause, print_queue_resume, update_printer_sec,
4435 update_printer, spoolss_addprinterex_level_2,
4436 _spoolss_setprinterdata
4438 PRINTER_ACCESS_USE:
4439 print_job_start
4441 JOB_ACCESS_ADMINISTER:
4442 print_job_delete, print_job_pause, print_job_resume,
4443 print_queue_purge
4445 ****************************************************************************/
4446 BOOL print_access_check(struct current_user *user, int snum, int access_type)
4448 SEC_DESC_BUF *secdesc = NULL;
4449 uint32 access_granted;
4450 NTSTATUS status;
4451 BOOL result;
4452 const char *pname;
4453 TALLOC_CTX *mem_ctx = NULL;
4454 extern struct current_user current_user;
4456 /* If user is NULL then use the current_user structure */
4458 if (!user)
4459 user = &current_user;
4461 /* Always allow root or printer admins to do anything */
4463 if (user->uid == 0 ||
4464 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
4465 return True;
4468 /* Get printer name */
4470 pname = PRINTERNAME(snum);
4472 if (!pname || !*pname) {
4473 errno = EACCES;
4474 return False;
4477 /* Get printer security descriptor */
4479 if(!(mem_ctx = talloc_init())) {
4480 errno = ENOMEM;
4481 return False;
4484 nt_printing_getsec(mem_ctx, pname, &secdesc);
4486 if (access_type == JOB_ACCESS_ADMINISTER) {
4487 SEC_DESC_BUF *parent_secdesc = secdesc;
4489 /* Create a child security descriptor to check permissions
4490 against. This is because print jobs are child objects
4491 objects of a printer. */
4493 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4495 /* Now this is the bit that really confuses me. The access
4496 type needs to be changed from JOB_ACCESS_ADMINISTER to
4497 PRINTER_ACCESS_ADMINISTER for this to work. Something
4498 to do with the child (job) object becoming like a
4499 printer?? -tpot */
4501 access_type = PRINTER_ACCESS_ADMINISTER;
4504 /* Check access */
4506 map_printer_permissions(secdesc->sec);
4508 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4509 &access_granted, &status);
4511 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4513 talloc_destroy(mem_ctx);
4515 if (!result)
4516 errno = EACCES;
4518 return result;
4521 /****************************************************************************
4522 Check the time parameters allow a print operation.
4523 *****************************************************************************/
4525 BOOL print_time_access_check(int snum)
4527 NT_PRINTER_INFO_LEVEL *printer = NULL;
4528 BOOL ok = False;
4529 time_t now = time(NULL);
4530 struct tm *t;
4531 uint32 mins;
4533 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4534 return False;
4536 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4537 ok = True;
4539 t = gmtime(&now);
4540 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4542 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4543 ok = True;
4545 free_a_printer(&printer, 2);
4547 if (!ok)
4548 errno = EACCES;
4550 return ok;