merging for 2.2.6pre1
[Samba.git] / source / printing / nt_printing.c
blob195028dc8a8f77b00b41b528649f78252daecf96
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.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 extern DOM_SID global_sid_World;
26 static TDB_CONTEXT *tdb_forms; /* used for forms files */
27 static TDB_CONTEXT *tdb_drivers; /* used for driver files */
28 static TDB_CONTEXT *tdb_printers; /* used for printers files */
30 #define FORMS_PREFIX "FORMS/"
31 #define DRIVERS_PREFIX "DRIVERS/"
32 #define DRIVER_INIT_PREFIX "DRIVER_INIT/"
33 #define PRINTERS_PREFIX "PRINTERS/"
34 #define SECDESC_PREFIX "SECDESC/"
35 #define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter"
37 #define NTDRIVERS_DATABASE_VERSION_1 1
38 #define NTDRIVERS_DATABASE_VERSION_2 2
39 #define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
41 #define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
43 /* Map generic permissions to printer object specific permissions */
45 GENERIC_MAPPING printer_generic_mapping = {
46 PRINTER_READ,
47 PRINTER_WRITE,
48 PRINTER_EXECUTE,
49 PRINTER_ALL_ACCESS
52 STANDARD_MAPPING printer_std_mapping = {
53 PRINTER_READ,
54 PRINTER_WRITE,
55 PRINTER_EXECUTE,
56 PRINTER_ALL_ACCESS
59 /* Map generic permissions to print server object specific permissions */
61 GENERIC_MAPPING printserver_generic_mapping = {
62 SERVER_READ,
63 SERVER_WRITE,
64 SERVER_EXECUTE,
65 SERVER_ALL_ACCESS
68 STANDARD_MAPPING printserver_std_mapping = {
69 SERVER_READ,
70 SERVER_WRITE,
71 SERVER_EXECUTE,
72 SERVER_ALL_ACCESS
75 /* We need one default form to support our default printer. Msoft adds the
76 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
77 array index). Letter is always first, so (for the current code) additions
78 always put things in the correct order. */
79 static nt_forms_struct default_forms[] = {
80 {"Letter",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
81 {"Letter Small",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
82 {"Tabloid",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
83 {"Ledger",0x1,0x696b8,0x44368,0x0,0x0,0x696b8,0x44368},
84 {"Legal",0x1,0x34b5c,0x56d10,0x0,0x0,0x34b5c,0x56d10},
85 {"Statement",0x1,0x221b4,0x34b5c,0x0,0x0,0x221b4,0x34b5c},
86 {"Executive",0x1,0x2cf56,0x411cc,0x0,0x0,0x2cf56,0x411cc},
87 {"A3",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
88 {"A4",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
89 {"A4 Small",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
90 {"A5",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
91 {"B4 (JIS)",0x1,0x3ebe8,0x58de0,0x0,0x0,0x3ebe8,0x58de0},
92 {"B5 (JIS)",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
93 {"Folio",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
94 {"Quarto",0x1,0x347d8,0x43238,0x0,0x0,0x347d8,0x43238},
95 {"10x14",0x1,0x3e030,0x56d10,0x0,0x0,0x3e030,0x56d10},
96 {"11x17",0x1,0x44368,0x696b8,0x0,0x0,0x44368,0x696b8},
97 {"Note",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
98 {"Envelope #9",0x1,0x18079,0x37091,0x0,0x0,0x18079,0x37091},
99 {"Envelope #10",0x1,0x19947,0x3ae94,0x0,0x0,0x19947,0x3ae94},
100 {"Envelope #11",0x1,0x1be7c,0x40565,0x0,0x0,0x1be7c,0x40565},
101 {"Envelope #12",0x1,0x1d74a,0x44368,0x0,0x0,0x1d74a,0x44368},
102 {"Envelope #14",0x1,0x1f018,0x47504,0x0,0x0,0x1f018,0x47504},
103 {"C size sheet",0x1,0x696b8,0x886d0,0x0,0x0,0x696b8,0x886d0},
104 {"D size sheet",0x1,0x886d0,0xd2d70,0x0,0x0,0x886d0,0xd2d70},
105 {"E size sheet",0x1,0xd2d70,0x110da0,0x0,0x0,0xd2d70,0x110da0},
106 {"Envelope DL",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
107 {"Envelope C5",0x1,0x278d0,0x37e88,0x0,0x0,0x278d0,0x37e88},
108 {"Envelope C3",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
109 {"Envelope C4",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
110 {"Envelope C6",0x1,0x1bd50,0x278d0,0x0,0x0,0x1bd50,0x278d0},
111 {"Envelope C65",0x1,0x1bd50,0x37e88,0x0,0x0,0x1bd50,0x37e88},
112 {"Envelope B4",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
113 {"Envelope B5",0x1,0x2af80,0x3d090,0x0,0x0,0x2af80,0x3d090},
114 {"Envelope B6",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
115 {"Envelope",0x1,0x1adb0,0x38270,0x0,0x0,0x1adb0,0x38270},
116 {"Envelope Monarch",0x1,0x18079,0x2e824,0x0,0x0,0x18079,0x2e824},
117 {"6 3/4 Envelope",0x1,0x167ab,0x284ec,0x0,0x0,0x167ab,0x284ec},
118 {"US Std Fanfold",0x1,0x5c3e1,0x44368,0x0,0x0,0x5c3e1,0x44368},
119 {"German Std Fanfold",0x1,0x34b5c,0x4a6a0,0x0,0x0,0x34b5c,0x4a6a0},
120 {"German Legal Fanfold",0x1,0x34b5c,0x509d8,0x0,0x0,0x34b5c,0x509d8},
121 {"B4 (ISO)",0x1,0x3d090,0x562e8,0x0,0x0,0x3d090,0x562e8},
122 {"Japanese Postcard",0x1,0x186a0,0x24220,0x0,0x0,0x186a0,0x24220},
123 {"9x11",0x1,0x37cf8,0x44368,0x0,0x0,0x37cf8,0x44368},
124 {"10x11",0x1,0x3e030,0x44368,0x0,0x0,0x3e030,0x44368},
125 {"15x11",0x1,0x5d048,0x44368,0x0,0x0,0x5d048,0x44368},
126 {"Envelope Invite",0x1,0x35b60,0x35b60,0x0,0x0,0x35b60,0x35b60},
127 {"Reserved48",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
128 {"Reserved49",0x1,0x1,0x1,0x0,0x0,0x1,0x1},
129 {"Letter Extra",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
130 {"Legal Extra",0x1,0x3ae94,0x5d048,0x0,0x0,0x3ae94,0x5d048},
131 {"Tabloid Extra",0x1,0x4a6a0,0x6f9f0,0x0,0x0,0x4a6a0,0x6f9f0},
132 {"A4 Extra",0x1,0x397c2,0x4eb16,0x0,0x0,0x397c2,0x4eb16},
133 {"Letter Transverse",0x1,0x34b5c,0x44368,0x0,0x0,0x34b5c,0x44368},
134 {"A4 Transverse",0x1,0x33450,0x48828,0x0,0x0,0x33450,0x48828},
135 {"Letter Extra Transverse",0x1,0x3ae94,0x4a6a0,0x0,0x0,0x3ae94,0x4a6a0},
136 {"Super A",0x1,0x376b8,0x56ea0,0x0,0x0,0x376b8,0x56ea0},
137 {"Super B",0x1,0x4a768,0x76e58,0x0,0x0,0x4a768,0x76e58},
138 {"Letter Plus",0x1,0x34b5c,0x4eb16,0x0,0x0,0x34b5c,0x4eb16},
139 {"A4 Plus",0x1,0x33450,0x50910,0x0,0x0,0x33450,0x50910},
140 {"A5 Transverse",0x1,0x24220,0x33450,0x0,0x0,0x24220,0x33450},
141 {"B5 (JIS) Transverse",0x1,0x2c6f0,0x3ebe8,0x0,0x0,0x2c6f0,0x3ebe8},
142 {"A3 Extra",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
143 {"A5 Extra",0x1,0x2a7b0,0x395f8,0x0,0x0,0x2a7b0,0x395f8},
144 {"B5 (ISO) Extra",0x1,0x31128,0x43620,0x0,0x0,0x31128,0x43620},
145 {"A2",0x1,0x668a0,0x91050,0x0,0x0,0x668a0,0x91050},
146 {"A3 Transverse",0x1,0x48828,0x668a0,0x0,0x0,0x48828,0x668a0},
147 {"A3 Extra Transverse",0x1,0x4e9d0,0x6ca48,0x0,0x0,0x4e9d0,0x6ca48},
148 {"Japanese Double Postcard",0x1,0x30d40,0x24220,0x0,0x0,0x30d40,0x24220},
149 {"A6",0x1,0x19a28,0x24220,0x0,0x0,0x19a28,0x24220},
150 {"Japanese Envelope Kaku #2",0x1,0x3a980,0x510e0,0x0,0x0,0x3a980,0x510e0},
151 {"Japanese Envelope Kaku #3",0x1,0x34bc0,0x43a08,0x0,0x0,0x34bc0,0x43a08},
152 {"Japanese Envelope Chou #3",0x1,0x1d4c0,0x395f8,0x0,0x0,0x1d4c0,0x395f8},
153 {"Japanese Envelope Chou #4",0x1,0x15f90,0x320c8,0x0,0x0,0x15f90,0x320c8},
154 {"Letter Rotated",0x1,0x44368,0x34b5c,0x0,0x0,0x44368,0x34b5c},
155 {"A3 Rotated",0x1,0x668a0,0x48828,0x0,0x0,0x668a0,0x48828},
156 {"A4 Rotated",0x1,0x48828,0x33450,0x0,0x0,0x48828,0x33450},
157 {"A5 Rotated",0x1,0x33450,0x24220,0x0,0x0,0x33450,0x24220},
158 {"B4 (JIS) Rotated",0x1,0x58de0,0x3ebe8,0x0,0x0,0x58de0,0x3ebe8},
159 {"B5 (JIS) Rotated",0x1,0x3ebe8,0x2c6f0,0x0,0x0,0x3ebe8,0x2c6f0},
160 {"Japanese Postcard Rotated",0x1,0x24220,0x186a0,0x0,0x0,0x24220,0x186a0},
161 {"Double Japan Postcard Rotated",0x1,0x24220,0x30d40,0x0,0x0,0x24220,0x30d40},
162 {"A6 Rotated",0x1,0x24220,0x19a28,0x0,0x0,0x24220,0x19a28},
163 {"Japan Envelope Kaku #2 Rotated",0x1,0x510e0,0x3a980,0x0,0x0,0x510e0,0x3a980},
164 {"Japan Envelope Kaku #3 Rotated",0x1,0x43a08,0x34bc0,0x0,0x0,0x43a08, 0x34bc0},
165 {"Japan Envelope Chou #3 Rotated",0x1,0x395f8,0x1d4c0,0x0,0x0,0x395f8,0x1d4c0},
166 {"Japan Envelope Chou #4 Rotated",0x1,0x320c8,0x15f90,0x0,0x0,0x320c8,0x15f90},
167 {"B6 (JIS)",0x1,0x1f400,0x2c6f0,0x0,0x0,0x1f400,0x2c6f0},
168 {"B6 (JIS) Rotated",0x1,0x2c6f0,0x1f400,0x0,0x0,0x2c6f0,0x1f400},
169 {"12x11",0x1,0x4a724,0x443e1,0x0,0x0,0x4a724,0x443e1},
170 {"Japan Envelope You #4",0x1,0x19a28,0x395f8,0x0,0x0,0x19a28,0x395f8},
171 {"Japan Envelope You #4 Rotated",0x1,0x395f8,0x19a28,0x0,0x0,0x395f8,0x19a28},
172 {"PRC 16K",0x1,0x2de60,0x3f7a0,0x0,0x0,0x2de60,0x3f7a0},
173 {"PRC 32K",0x1,0x1fbd0,0x2cec0,0x0,0x0,0x1fbd0,0x2cec0},
174 {"PRC 32K(Big)",0x1,0x222e0,0x318f8,0x0,0x0,0x222e0,0x318f8},
175 {"PRC Envelope #1",0x1,0x18e70,0x28488,0x0,0x0,0x18e70,0x28488},
176 {"PRC Envelope #2",0x1,0x18e70,0x2af80,0x0,0x0,0x18e70,0x2af80},
177 {"PRC Envelope #3",0x1,0x1e848,0x2af80,0x0,0x0,0x1e848,0x2af80},
178 {"PRC Envelope #4",0x1,0x1adb0,0x32c80,0x0,0x0,0x1adb0,0x32c80},
179 {"PRC Envelope #5",0x1,0x1adb0,0x35b60,0x0,0x0,0x1adb0,0x35b60},
180 {"PRC Envelope #6",0x1,0x1d4c0,0x38270,0x0,0x0,0x1d4c0,0x38270},
181 {"PRC Envelope #7",0x1,0x27100,0x38270,0x0,0x0,0x27100,0x38270},
182 {"PRC Envelope #8",0x1,0x1d4c0,0x4b708,0x0,0x0,0x1d4c0,0x4b708},
183 {"PRC Envelope #9",0x1,0x37e88,0x4f1a0,0x0,0x0,0x37e88,0x4f1a0},
184 {"PRC Envelope #10",0x1,0x4f1a0,0x6fd10,0x0,0x0,0x4f1a0,0x6fd10},
185 {"PRC 16K Rotated",0x1,0x3f7a0,0x2de60,0x0,0x0,0x3f7a0,0x2de60},
186 {"PRC 32K Rotated",0x1,0x2cec0,0x1fbd0,0x0,0x0,0x2cec0,0x1fbd0},
187 {"PRC 32K(Big) Rotated",0x1,0x318f8,0x222e0,0x0,0x0,0x318f8,0x222e0},
188 {"PRC Envelope #1 Rotated",0x1,0x28488,0x18e70,0x0,0x0,0x28488,0x18e70},
189 {"PRC Envelope #2 Rotated",0x1,0x2af80,0x18e70,0x0,0x0,0x2af80,0x18e70},
190 {"PRC Envelope #3 Rotated",0x1,0x2af80,0x1e848,0x0,0x0,0x2af80,0x1e848},
191 {"PRC Envelope #4 Rotated",0x1,0x32c80,0x1adb0,0x0,0x0,0x32c80,0x1adb0},
192 {"PRC Envelope #5 Rotated",0x1,0x35b60,0x1adb0,0x0,0x0,0x35b60,0x1adb0},
193 {"PRC Envelope #6 Rotated",0x1,0x38270,0x1d4c0,0x0,0x0,0x38270,0x1d4c0},
194 {"PRC Envelope #7 Rotated",0x1,0x38270,0x27100,0x0,0x0,0x38270,0x27100},
195 {"PRC Envelope #8 Rotated",0x1,0x4b708,0x1d4c0,0x0,0x0,0x4b708,0x1d4c0},
196 {"PRC Envelope #9 Rotated",0x1,0x4f1a0,0x37e88,0x0,0x0,0x4f1a0,0x37e88},
197 {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
200 static BOOL upgrade_to_version_3(void)
202 TDB_DATA kbuf, newkey, dbuf;
204 DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
206 for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
207 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
209 dbuf = tdb_fetch(tdb_drivers, kbuf);
211 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
212 DEBUG(0,("upgrade_to_version_3:moving form\n"));
213 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
214 DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
215 return False;
217 if (tdb_delete(tdb_drivers, kbuf) != 0) {
218 DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
219 return False;
223 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
224 DEBUG(0,("upgrade_to_version_3:moving printer\n"));
225 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
226 DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
227 return False;
229 if (tdb_delete(tdb_drivers, kbuf) != 0) {
230 DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
231 return False;
235 if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
236 DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
237 if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
238 DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
239 return False;
241 if (tdb_delete(tdb_drivers, kbuf) != 0) {
242 DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
243 return False;
247 SAFE_FREE(dbuf.dptr);
250 return True;
253 /****************************************************************************
254 Open the NT printing tdb.
255 ****************************************************************************/
257 BOOL nt_printing_init(void)
259 static pid_t local_pid;
260 char *vstring = "INFO/version";
262 if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
263 return True;
265 tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
266 if (!tdb_drivers) {
267 DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
268 lock_path("ntdrivers.tdb"), strerror(errno) ));
269 return False;
272 tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
273 if (!tdb_printers) {
274 DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
275 lock_path("ntprinters.tdb"), strerror(errno) ));
276 return False;
279 tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
280 if (!tdb_forms) {
281 DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
282 lock_path("ntforms.tdb"), strerror(errno) ));
283 return False;
286 local_pid = sys_getpid();
288 /* handle a Samba upgrade */
289 tdb_lock_bystring(tdb_drivers, vstring);
291 int32 vers_id;
293 /* Cope with byte-reversed older versions of the db. */
294 vers_id = tdb_fetch_int32(tdb_drivers, vstring);
295 if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
296 /* Written on a bigendian machine with old fetch_int code. Save as le. */
297 /* The only upgrade between V2 and V3 is to save the version in little-endian. */
298 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
299 vers_id = NTDRIVERS_DATABASE_VERSION;
302 if (vers_id != NTDRIVERS_DATABASE_VERSION) {
304 if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
305 if (!upgrade_to_version_3())
306 return False;
307 } else
308 tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
310 tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
313 tdb_unlock_bystring(tdb_drivers, vstring);
315 update_c_setprinter(True);
318 * register callback to handle updating printers as new
319 * drivers are installed
321 message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
323 return True;
326 /*******************************************************************
327 tdb traversal function for counting printers.
328 ********************************************************************/
330 static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key,
331 TDB_DATA data, void *context)
333 int *printer_count = (int*)context;
335 if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) {
336 (*printer_count)++;
337 DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count));
340 return 0;
343 /*******************************************************************
344 Update the spooler global c_setprinter. This variable is initialized
345 when the parent smbd starts with the number of existing printers. It
346 is monotonically increased by the current number of printers *after*
347 each add or delete printer RPC. Only Microsoft knows why... JRR020119
348 ********************************************************************/
350 uint32 update_c_setprinter(BOOL initialize)
352 int32 c_setprinter;
353 int32 printer_count = 0;
355 tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
357 /* Traverse the tdb, counting the printers */
358 tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count);
360 /* If initializing, set c_setprinter to current printers count
361 * otherwise, bump it by the current printer count
363 if (!initialize)
364 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count;
365 else
366 c_setprinter = printer_count;
368 DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter));
369 tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter);
371 tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER);
373 return (uint32)c_setprinter;
376 /*******************************************************************
377 Get the spooler global c_setprinter, accounting for initialization.
378 ********************************************************************/
380 uint32 get_c_setprinter(void)
382 int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER);
384 if (c_setprinter == (int32)-1)
385 c_setprinter = update_c_setprinter(True);
387 DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter));
389 return (uint32)c_setprinter;
392 /****************************************************************************
393 Get builtin form struct list.
394 ****************************************************************************/
396 int get_builtin_ntforms(nt_forms_struct **list)
398 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
399 return sizeof(default_forms) / sizeof(default_forms[0]);
402 /****************************************************************************
403 get a builtin form struct
404 ****************************************************************************/
406 BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
408 int i,count;
409 fstring form_name;
410 unistr2_to_dos(form_name, uni_formname, sizeof(form_name)-1);
411 DEBUGADD(6,("Looking for builtin form %s \n", form_name));
412 count = sizeof(default_forms) / sizeof(default_forms[0]);
413 for (i=0;i<count;i++) {
414 if (strequal(form_name,default_forms[i].name)) {
415 DEBUGADD(6,("Found builtin form %s \n", form_name));
416 memcpy(form,&default_forms[i],sizeof(*form));
417 break;
421 return (i !=count);
424 /****************************************************************************
425 get a form struct list
426 ****************************************************************************/
427 int get_ntforms(nt_forms_struct **list)
429 TDB_DATA kbuf, newkey, dbuf;
430 nt_forms_struct *tl;
431 nt_forms_struct form;
432 int ret;
433 int i;
434 int n = 0;
436 for (kbuf = tdb_firstkey(tdb_forms);
437 kbuf.dptr;
438 newkey = tdb_nextkey(tdb_forms, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
439 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
441 dbuf = tdb_fetch(tdb_forms, kbuf);
442 if (!dbuf.dptr) continue;
444 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
445 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
446 &i, &form.flag, &form.width, &form.length, &form.left,
447 &form.top, &form.right, &form.bottom);
448 SAFE_FREE(dbuf.dptr);
449 if (ret != dbuf.dsize) continue;
451 tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
452 if (!tl) {
453 DEBUG(0,("get_ntforms: Realloc fail.\n"));
454 return 0;
456 *list = tl;
457 (*list)[n] = form;
458 n++;
462 return n;
465 /****************************************************************************
466 write a form struct list
467 ****************************************************************************/
468 int write_ntforms(nt_forms_struct **list, int number)
470 pstring buf, key;
471 int len;
472 TDB_DATA kbuf,dbuf;
473 int i;
475 for (i=0;i<number;i++) {
476 /* save index, so list is rebuilt in correct order */
477 len = tdb_pack(buf, sizeof(buf), "dddddddd",
478 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
479 (*list)[i].left, (*list)[i].top, (*list)[i].right,
480 (*list)[i].bottom);
481 if (len > sizeof(buf)) break;
482 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[i].name);
483 dos_to_unix(key); /* Convert key to unix-codepage */
484 kbuf.dsize = strlen(key)+1;
485 kbuf.dptr = key;
486 dbuf.dsize = len;
487 dbuf.dptr = buf;
488 if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) break;
491 return i;
494 /****************************************************************************
495 add a form struct at the end of the list
496 ****************************************************************************/
497 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
499 int n=0;
500 BOOL update;
501 fstring form_name;
502 nt_forms_struct *tl;
505 * NT tries to add forms even when
506 * they are already in the base
507 * only update the values if already present
510 update=False;
512 unistr2_to_dos(form_name, &form->name, sizeof(form_name)-1);
513 for (n=0; n<*count; n++) {
514 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
515 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
516 update=True;
517 break;
521 if (update==False) {
522 if((tl=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL) {
523 DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
524 return False;
526 *list = tl;
527 unistr2_to_dos((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
528 (*count)++;
531 (*list)[n].flag=form->flags;
532 (*list)[n].width=form->size_x;
533 (*list)[n].length=form->size_y;
534 (*list)[n].left=form->left;
535 (*list)[n].top=form->top;
536 (*list)[n].right=form->right;
537 (*list)[n].bottom=form->bottom;
539 return True;
542 /****************************************************************************
543 delete a named form struct
544 ****************************************************************************/
545 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
547 pstring key;
548 TDB_DATA kbuf;
549 int n=0;
550 fstring form_name;
552 *ret = WERR_OK;
554 unistr2_to_dos(form_name, del_name, sizeof(form_name)-1);
556 for (n=0; n<*count; n++) {
557 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
558 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
559 break;
563 if (n == *count) {
564 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
565 *ret = WERR_INVALID_PARAM;
566 return False;
569 slprintf(key, sizeof(key)-1, "%s%s", FORMS_PREFIX, (*list)[n].name);
570 dos_to_unix(key); /* Convert key to unix-codepage */
571 kbuf.dsize = strlen(key)+1;
572 kbuf.dptr = key;
573 if (tdb_delete(tdb_forms, kbuf) != 0) {
574 *ret = WERR_NOMEM;
575 return False;
578 return True;
581 /****************************************************************************
582 update a form struct
583 ****************************************************************************/
584 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
586 int n=0;
587 fstring form_name;
588 unistr2_to_dos(form_name, &(form->name), sizeof(form_name)-1);
590 DEBUG(106, ("[%s]\n", form_name));
591 for (n=0; n<count; n++)
593 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
594 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
595 break;
598 if (n==count) return;
600 (*list)[n].flag=form->flags;
601 (*list)[n].width=form->size_x;
602 (*list)[n].length=form->size_y;
603 (*list)[n].left=form->left;
604 (*list)[n].top=form->top;
605 (*list)[n].right=form->right;
606 (*list)[n].bottom=form->bottom;
609 /****************************************************************************
610 get the nt drivers list
612 traverse the database and look-up the matching names
613 ****************************************************************************/
614 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
616 int total=0;
617 fstring short_archi;
618 fstring *fl;
619 pstring key;
620 TDB_DATA kbuf, newkey;
622 get_short_archi(short_archi, architecture);
623 slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
625 for (kbuf = tdb_firstkey(tdb_drivers);
626 kbuf.dptr;
627 newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
628 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
630 if((fl = Realloc(*list, sizeof(fstring)*(total+1))) == NULL) {
631 DEBUG(0,("get_ntdrivers: failed to enlarge list!\n"));
632 return -1;
634 else *list = fl;
636 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
637 total++;
640 return(total);
643 /****************************************************************************
644 function to do the mapping between the long architecture name and
645 the short one.
646 ****************************************************************************/
647 BOOL get_short_archi(char *short_archi, char *long_archi)
649 struct table {
650 char *long_archi;
651 char *short_archi;
654 struct table archi_table[]=
656 {"Windows 4.0", "WIN40" },
657 {"Windows NT x86", "W32X86" },
658 {"Windows NT R4000", "W32MIPS" },
659 {"Windows NT Alpha_AXP", "W32ALPHA" },
660 {"Windows NT PowerPC", "W32PPC" },
661 {NULL, "" }
664 int i=-1;
666 DEBUG(107,("Getting architecture dependant directory\n"));
667 do {
668 i++;
669 } while ( (archi_table[i].long_archi!=NULL ) &&
670 StrCaseCmp(long_archi, archi_table[i].long_archi) );
672 if (archi_table[i].long_archi==NULL) {
673 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
674 return False;
677 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
679 DEBUGADD(108,("index: [%d]\n", i));
680 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
681 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
683 return True;
686 /****************************************************************************
687 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
688 There are two case to be covered here: PE (Portable Executable) and NE (New
689 Executable) files. Both files support the same INFO structure, but PE files
690 store the signature in unicode, and NE files store it as !unicode.
691 returns -1 on error, 1 on version info found, and 0 on no version info found.
692 ****************************************************************************/
694 static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
696 int i;
697 char *buf;
698 ssize_t byte_count;
700 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
701 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
702 fname, PE_HEADER_SIZE));
703 goto error_exit;
706 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
707 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
708 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
709 fname, byte_count));
710 goto no_version_info;
713 /* Is this really a DOS header? */
714 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
715 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
716 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
717 goto no_version_info;
720 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
721 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
722 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
723 fname, errno));
724 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
725 goto no_version_info;
728 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
729 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
730 fname, byte_count));
731 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
732 goto no_version_info;
735 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
736 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
737 int num_sections;
738 int section_table_bytes;
740 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
741 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
742 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
743 /* At this point, we assume the file is in error. It still could be somthing
744 * else besides a PE file, but it unlikely at this point.
746 goto error_exit;
749 /* get the section table */
750 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
751 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
752 SAFE_FREE(buf);
753 if ((buf=malloc(section_table_bytes)) == NULL) {
754 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
755 fname, section_table_bytes));
756 goto error_exit;
759 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
760 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
761 fname, byte_count));
762 goto error_exit;
765 /* Iterate the section table looking for the resource section ".rsrc" */
766 for (i = 0; i < num_sections; i++) {
767 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
769 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
770 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
771 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
773 SAFE_FREE(buf);
774 if ((buf=malloc(section_bytes)) == NULL) {
775 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
776 fname, section_bytes));
777 goto error_exit;
780 /* Seek to the start of the .rsrc section info */
781 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
782 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
783 fname, errno));
784 goto error_exit;
787 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
788 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
789 fname, byte_count));
790 goto error_exit;
793 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
794 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
795 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
796 /* Align to next long address */
797 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
799 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
800 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
801 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
803 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
804 fname, *major, *minor,
805 (*major>>16)&0xffff, *major&0xffff,
806 (*minor>>16)&0xffff, *minor&0xffff));
807 SAFE_FREE(buf);
808 return 1;
815 /* Version info not found, fall back to origin date/time */
816 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
817 SAFE_FREE(buf);
818 return 0;
820 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
821 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
822 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
823 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
824 /* At this point, we assume the file is in error. It still could be somthing
825 * else besides a NE file, but it unlikely at this point. */
826 goto error_exit;
829 /* Allocate a bit more space to speed up things */
830 SAFE_FREE(buf);
831 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
832 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
833 fname, PE_HEADER_SIZE));
834 goto error_exit;
837 /* This is a HACK! I got tired of trying to sort through the messy
838 * 'NE' file format. If anyone wants to clean this up please have at
839 * it, but this works. 'NE' files will eventually fade away. JRR */
840 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
841 /* Cover case that should not occur in a well formed 'NE' .dll file */
842 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
844 for(i=0; i<byte_count; i++) {
845 /* Fast skip past data that can't possibly match */
846 if (buf[i] != 'V') continue;
848 /* Potential match data crosses buf boundry, move it to beginning
849 * of buf, and fill the buf with as much as it will hold. */
850 if (i>byte_count-VS_VERSION_INFO_SIZE) {
851 int bc;
853 memcpy(buf, &buf[i], byte_count-i);
854 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
855 (byte_count-i))) < 0) {
857 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
858 fname, errno));
859 goto error_exit;
862 byte_count = bc + (byte_count - i);
863 if (byte_count<VS_VERSION_INFO_SIZE) break;
865 i = 0;
868 /* Check that the full signature string and the magic number that
869 * follows exist (not a perfect solution, but the chances that this
870 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
871 * twice, as it is simpler to read the code. */
872 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
873 /* Compute skip alignment to next long address */
874 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
875 sizeof(VS_SIGNATURE)) & 3;
876 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
878 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
879 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
880 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
881 fname, *major, *minor,
882 (*major>>16)&0xffff, *major&0xffff,
883 (*minor>>16)&0xffff, *minor&0xffff));
884 SAFE_FREE(buf);
885 return 1;
890 /* Version info not found, fall back to origin date/time */
891 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
892 SAFE_FREE(buf);
893 return 0;
895 } else
896 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
897 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
898 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
900 no_version_info:
901 SAFE_FREE(buf);
902 return 0;
904 error_exit:
905 SAFE_FREE(buf);
906 return -1;
909 /****************************************************************************
910 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
911 share one or more files. During the MS installation process files are checked
912 to insure that only a newer version of a shared file is installed over an
913 older version. There are several possibilities for this comparison. If there
914 is no previous version, the new one is newer (obviously). If either file is
915 missing the version info structure, compare the creation date (on Unix use
916 the modification date). Otherwise chose the numerically larger version number.
917 ****************************************************************************/
918 static int file_version_is_newer(connection_struct *conn, fstring new_file,
919 fstring old_file)
921 BOOL use_version = True;
922 pstring filepath;
924 uint32 new_major;
925 uint32 new_minor;
926 time_t new_create_time;
928 uint32 old_major;
929 uint32 old_minor;
930 time_t old_create_time;
932 int access_mode;
933 int action;
934 files_struct *fsp = NULL;
935 SMB_STRUCT_STAT st;
936 SMB_STRUCT_STAT stat_buf;
937 BOOL bad_path;
939 ZERO_STRUCT(st);
940 ZERO_STRUCT(stat_buf);
941 new_create_time = (time_t)0;
942 old_create_time = (time_t)0;
944 /* Get file version info (if available) for previous file (if it exists) */
945 pstrcpy(filepath, old_file);
947 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
949 fsp = open_file_shared(conn, filepath, &stat_buf,
950 SET_OPEN_MODE(DOS_OPEN_RDONLY),
951 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
952 0, 0, &access_mode, &action);
953 if (!fsp) {
954 /* Old file not found, so by definition new file is in fact newer */
955 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
956 filepath, errno));
957 return True;
959 } else {
960 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
961 if (ret == -1) goto error_exit;
963 if (!ret) {
964 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
965 old_file));
966 use_version = False;
968 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
969 old_create_time = st.st_mtime;
970 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
972 close_file(fsp, True);
974 /* Get file version info (if available) for new file */
975 pstrcpy(filepath, new_file);
976 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
978 fsp = open_file_shared(conn, filepath, &stat_buf,
979 SET_OPEN_MODE(DOS_OPEN_RDONLY),
980 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
981 0, 0, &access_mode, &action);
982 if (!fsp) {
983 /* New file not found, this shouldn't occur if the caller did its job */
984 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
985 filepath, errno));
986 goto error_exit;
988 } else {
989 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
990 if (ret == -1) goto error_exit;
992 if (!ret) {
993 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
994 new_file));
995 use_version = False;
997 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
998 new_create_time = st.st_mtime;
999 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1001 close_file(fsp, True);
1003 if (use_version && (new_major != old_major || new_minor != old_minor)) {
1004 /* Compare versions and choose the larger version number */
1005 if (new_major > old_major ||
1006 (new_major == old_major && new_minor > old_minor)) {
1008 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1009 return True;
1011 else {
1012 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1013 return False;
1016 } else {
1017 /* Compare modification time/dates and choose the newest time/date */
1018 if (new_create_time > old_create_time) {
1019 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1020 return True;
1022 else {
1023 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1024 return False;
1028 error_exit:
1029 if(fsp)
1030 close_file(fsp, True);
1031 return -1;
1034 /****************************************************************************
1035 Determine the correct cVersion associated with an architecture and driver
1036 ****************************************************************************/
1037 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
1038 struct current_user *user, WERROR *perr)
1040 int cversion;
1041 int access_mode;
1042 int action;
1043 pstring driverpath;
1044 fstring user_name;
1045 fstring null_pw;
1046 files_struct *fsp = NULL;
1047 BOOL bad_path;
1048 int ecode;
1049 SMB_STRUCT_STAT st;
1050 struct passwd *pass;
1051 connection_struct *conn;
1053 ZERO_STRUCT(st);
1055 *perr = WERR_INVALID_PARAM;
1057 /* If architecture is Windows 95/98/ME, the version is always 0. */
1058 if (strcmp(architecture, "WIN40") == 0) {
1059 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
1060 *perr = WERR_OK;
1061 return 0;
1064 become_root();
1065 pass = sys_getpwuid(user->uid);
1066 if(pass == NULL) {
1067 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
1068 (unsigned int)user->uid ));
1069 unbecome_root();
1070 *perr = WERR_ACCESS_DENIED;
1071 return -1;
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 fstrcpy(user_name, pass->pw_name );
1080 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
1082 /* Null password is ok - we are already an authenticated user... */
1083 *null_pw = '\0';
1084 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1085 unbecome_root();
1087 if (conn == NULL) {
1088 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
1089 *perr = W_ERROR(ecode);
1090 return -1;
1093 /* We are temporarily becoming the connection user. */
1094 if (!become_user(conn, conn->vuid)) {
1095 DEBUG(0,("get_correct_cversion: Can't become user!\n"));
1096 *perr = WERR_ACCESS_DENIED;
1097 return -1;
1100 /* Open the driver file (Portable Executable format) and determine the
1101 * deriver the cversion. */
1102 slprintf(driverpath, sizeof(driverpath)-1, "%s/%s", architecture, driverpath_in);
1104 unix_convert(driverpath,conn,NULL,&bad_path,&st);
1106 fsp = open_file_shared(conn, driverpath, &st,
1107 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1108 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1109 0, 0, &access_mode, &action);
1110 if (!fsp) {
1111 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
1112 driverpath, errno));
1113 *perr = WERR_ACCESS_DENIED;
1114 goto error_exit;
1116 else {
1117 uint32 major;
1118 uint32 minor;
1119 int ret = get_file_version(fsp, driverpath, &major, &minor);
1120 if (ret == -1) goto error_exit;
1122 if (!ret) {
1123 DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
1124 goto error_exit;
1128 * This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
1129 * for more details. Version in this case is not just the version of the
1130 * file, but the version in the sense of kernal mode (2) vs. user mode
1131 * (3) drivers. Other bits of the version fields are the version info.
1132 * JRR 010716
1134 cversion = major & 0x0000ffff;
1135 switch (cversion) {
1136 case 2: /* WinNT drivers */
1137 case 3: /* Win2K drivers */
1138 break;
1140 default:
1141 DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
1142 driverpath, cversion));
1143 goto error_exit;
1146 DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
1147 driverpath, major, minor));
1150 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
1151 driverpath, cversion));
1153 close_file(fsp, True);
1154 close_cnum(conn, user->vuid);
1155 unbecome_user();
1156 *perr = WERR_OK;
1157 return cversion;
1160 error_exit:
1162 if(fsp)
1163 close_file(fsp, True);
1165 close_cnum(conn, user->vuid);
1166 unbecome_user();
1167 return -1;
1170 /****************************************************************************
1171 ****************************************************************************/
1172 static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
1173 struct current_user *user)
1175 fstring architecture;
1176 fstring new_name;
1177 char *p;
1178 int i;
1179 WERROR err;
1181 /* clean up the driver name.
1182 * we can get .\driver.dll
1183 * or worse c:\windows\system\driver.dll !
1185 /* using an intermediate string to not have overlaping memcpy()'s */
1186 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1187 fstrcpy(new_name, p+1);
1188 fstrcpy(driver->driverpath, new_name);
1191 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1192 fstrcpy(new_name, p+1);
1193 fstrcpy(driver->datafile, new_name);
1196 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1197 fstrcpy(new_name, p+1);
1198 fstrcpy(driver->configfile, new_name);
1201 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1202 fstrcpy(new_name, p+1);
1203 fstrcpy(driver->helpfile, new_name);
1206 if (driver->dependentfiles) {
1207 for (i=0; *driver->dependentfiles[i]; i++) {
1208 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1209 fstrcpy(new_name, p+1);
1210 fstrcpy(driver->dependentfiles[i], new_name);
1215 get_short_archi(architecture, driver->environment);
1217 /* jfm:7/16/2000 the client always sends the cversion=0.
1218 * The server should check which version the driver is by reading
1219 * the PE header of driver->driverpath.
1221 * For Windows 95/98 the version is 0 (so the value sent is correct)
1222 * For Windows NT (the architecture doesn't matter)
1223 * NT 3.1: cversion=0
1224 * NT 3.5/3.51: cversion=1
1225 * NT 4: cversion=2
1226 * NT2K: cversion=3
1228 if ((driver->cversion = get_correct_cversion( architecture,
1229 driver->driverpath, user, &err)) == -1)
1230 return err;
1232 return WERR_OK;
1235 /****************************************************************************
1236 ****************************************************************************/
1237 static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
1238 struct current_user *user)
1240 fstring architecture;
1241 fstring new_name;
1242 char *p;
1243 int i;
1244 WERROR err;
1246 /* clean up the driver name.
1247 * we can get .\driver.dll
1248 * or worse c:\windows\system\driver.dll !
1250 /* using an intermediate string to not have overlaping memcpy()'s */
1251 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
1252 fstrcpy(new_name, p+1);
1253 fstrcpy(driver->driverpath, new_name);
1256 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
1257 fstrcpy(new_name, p+1);
1258 fstrcpy(driver->datafile, new_name);
1261 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
1262 fstrcpy(new_name, p+1);
1263 fstrcpy(driver->configfile, new_name);
1266 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
1267 fstrcpy(new_name, p+1);
1268 fstrcpy(driver->helpfile, new_name);
1271 if (driver->dependentfiles) {
1272 for (i=0; *driver->dependentfiles[i]; i++) {
1273 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
1274 fstrcpy(new_name, p+1);
1275 fstrcpy(driver->dependentfiles[i], new_name);
1280 get_short_archi(architecture, driver->environment);
1282 /* jfm:7/16/2000 the client always sends the cversion=0.
1283 * The server should check which version the driver is by reading
1284 * the PE header of driver->driverpath.
1286 * For Windows 95/98 the version is 0 (so the value sent is correct)
1287 * For Windows NT (the architecture doesn't matter)
1288 * NT 3.1: cversion=0
1289 * NT 3.5/3.51: cversion=1
1290 * NT 4: cversion=2
1291 * NT2K: cversion=3
1293 if ((driver->version = get_correct_cversion(architecture,
1294 driver->driverpath, user, &err)) == -1)
1295 return err;
1297 return WERR_OK;
1300 /****************************************************************************
1301 ****************************************************************************/
1302 WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
1303 uint32 level, struct current_user *user)
1305 switch (level) {
1306 case 3:
1308 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1309 driver=driver_abstract.info_3;
1310 return clean_up_driver_struct_level_3(driver, user);
1312 case 6:
1314 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
1315 driver=driver_abstract.info_6;
1316 return clean_up_driver_struct_level_6(driver, user);
1318 default:
1319 return WERR_INVALID_PARAM;
1323 /****************************************************************************
1324 This function sucks and should be replaced. JRA.
1325 ****************************************************************************/
1327 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
1329 dst->cversion = src->version;
1331 fstrcpy( dst->name, src->name);
1332 fstrcpy( dst->environment, src->environment);
1333 fstrcpy( dst->driverpath, src->driverpath);
1334 fstrcpy( dst->datafile, src->datafile);
1335 fstrcpy( dst->configfile, src->configfile);
1336 fstrcpy( dst->helpfile, src->helpfile);
1337 fstrcpy( dst->monitorname, src->monitorname);
1338 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
1339 dst->dependentfiles = src->dependentfiles;
1342 #if 0 /* Debugging function */
1344 static char* ffmt(unsigned char *c){
1345 int i;
1346 static char ffmt_str[17];
1348 for (i=0; i<16; i++) {
1349 if ((c[i] < ' ') || (c[i] > '~'))
1350 ffmt_str[i]='.';
1351 else
1352 ffmt_str[i]=c[i];
1354 ffmt_str[16]='\0';
1355 return ffmt_str;
1358 #endif
1360 /****************************************************************************
1361 ****************************************************************************/
1362 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
1363 struct current_user *user, WERROR *perr)
1365 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1366 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1367 fstring architecture;
1368 pstring new_dir;
1369 pstring old_name;
1370 pstring new_name;
1371 fstring user_name;
1372 fstring null_pw;
1373 connection_struct *conn;
1374 pstring inbuf;
1375 pstring outbuf;
1376 struct passwd *pass;
1377 int ecode;
1378 int ver = 0;
1379 int i;
1381 memset(inbuf, '\0', sizeof(inbuf));
1382 memset(outbuf, '\0', sizeof(outbuf));
1383 *perr = WERR_OK;
1385 if (level==3)
1386 driver=driver_abstract.info_3;
1387 else if (level==6) {
1388 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1389 driver = &converted_driver;
1390 } else {
1391 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1392 return False;
1395 get_short_archi(architecture, driver->environment);
1397 become_root();
1398 pass = sys_getpwuid(user->uid);
1399 if(pass == NULL) {
1400 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1401 (unsigned int)user->uid ));
1402 unbecome_root();
1403 return False;
1407 * Connect to the print$ share under the same account as the user connected to the rpc pipe.
1408 * Note we must be root to do this.
1411 fstrcpy(user_name, pass->pw_name );
1412 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1414 /* Null password is ok - we are already an authenticated user... */
1415 *null_pw = '\0';
1416 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1417 unbecome_root();
1419 if (conn == NULL) {
1420 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1421 *perr = W_ERROR(ecode);
1422 return False;
1426 * Save who we are - we are temporarily becoming the connection user.
1429 if (!become_user(conn, conn->vuid)) {
1430 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1431 return False;
1435 * make the directories version and version\driver_name
1436 * under the architecture directory.
1438 DEBUG(5,("Creating first directory\n"));
1439 slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
1440 mkdir_internal(conn, new_dir);
1442 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1443 * listed for this driver which has already been moved, skip it (note:
1444 * drivers may list the same file name several times. Then check if the
1445 * file already exists in archi\cversion\, if so, check that the version
1446 * info (or time stamps if version info is unavailable) is newer (or the
1447 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1448 * Otherwise, delete the file.
1450 * If a file is not moved to archi\cversion\ because of an error, all the
1451 * rest of the 'unmoved' driver files are removed from archi\. If one or
1452 * more of the driver's files was already moved to archi\cversion\, it
1453 * potentially leaves the driver in a partially updated state. Version
1454 * trauma will most likely occur if an client attempts to use any printer
1455 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1456 * done is appropriate... later JRR
1459 DEBUG(5,("Moving files now !\n"));
1461 if (driver->driverpath && strlen(driver->driverpath)) {
1462 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
1463 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
1464 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1465 NTSTATUS status;
1466 status = rename_internals(conn, new_name, old_name, True);
1467 if (!NT_STATUS_IS_OK(status)) {
1468 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1469 new_name, old_name));
1470 *perr = ntstatus_to_werror(status);
1471 unlink_internals(conn, 0, new_name);
1472 ver = -1;
1475 else
1476 unlink_internals(conn, 0, new_name);
1479 if (driver->datafile && strlen(driver->datafile)) {
1480 if (!strequal(driver->datafile, driver->driverpath)) {
1481 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
1482 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
1483 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1484 NTSTATUS status;
1485 status = rename_internals(conn, new_name, old_name, True);
1486 if (!NT_STATUS_IS_OK(status)) {
1487 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1488 new_name, old_name));
1489 *perr = ntstatus_to_werror(status);
1490 unlink_internals(conn, 0, new_name);
1491 ver = -1;
1494 else
1495 unlink_internals(conn, 0, new_name);
1499 if (driver->configfile && strlen(driver->configfile)) {
1500 if (!strequal(driver->configfile, driver->driverpath) &&
1501 !strequal(driver->configfile, driver->datafile)) {
1502 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
1503 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
1504 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1505 NTSTATUS status;
1506 status = rename_internals(conn, new_name, old_name, True);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1509 new_name, old_name));
1510 *perr = ntstatus_to_werror(status);
1511 unlink_internals(conn, 0, new_name);
1512 ver = -1;
1515 else
1516 unlink_internals(conn, 0, new_name);
1520 if (driver->helpfile && strlen(driver->helpfile)) {
1521 if (!strequal(driver->helpfile, driver->driverpath) &&
1522 !strequal(driver->helpfile, driver->datafile) &&
1523 !strequal(driver->helpfile, driver->configfile)) {
1524 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
1525 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
1526 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1527 NTSTATUS status;
1528 status = rename_internals(conn, new_name, old_name, True);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1531 new_name, old_name));
1532 *perr = ntstatus_to_werror(status);
1533 unlink_internals(conn, 0, new_name);
1534 ver = -1;
1537 else
1538 unlink_internals(conn, 0, new_name);
1542 if (driver->dependentfiles) {
1543 for (i=0; *driver->dependentfiles[i]; i++) {
1544 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1545 !strequal(driver->dependentfiles[i], driver->datafile) &&
1546 !strequal(driver->dependentfiles[i], driver->configfile) &&
1547 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1548 int j;
1549 for (j=0; j < i; j++) {
1550 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1551 goto NextDriver;
1555 slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
1556 slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
1557 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1558 NTSTATUS status;
1559 status = rename_internals(conn, new_name, old_name, True);
1560 if (!NT_STATUS_IS_OK(status)) {
1561 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1562 new_name, old_name));
1563 *perr = ntstatus_to_werror(status);
1564 unlink_internals(conn, 0, new_name);
1565 ver = -1;
1568 else
1569 unlink_internals(conn, 0, new_name);
1571 NextDriver: ;
1575 close_cnum(conn, user->vuid);
1576 unbecome_user();
1578 return ver == -1 ? False : True;
1581 /****************************************************************************
1582 ****************************************************************************/
1583 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1585 int len, buflen;
1586 fstring architecture;
1587 pstring directory;
1588 pstring temp_name;
1589 pstring key;
1590 char *buf;
1591 int i, ret;
1592 TDB_DATA kbuf, dbuf;
1594 get_short_archi(architecture, driver->environment);
1596 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1597 * \\server is added in the rpc server layer.
1598 * It does make sense to NOT store the server's name in the printer TDB.
1601 slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
1603 /* .inf files do not always list a file for each of the four standard files.
1604 * Don't prepend a path to a null filename, or client claims:
1605 * "The server on which the printer resides does not have a suitable
1606 * <printer driver name> printer driver installed. Click OK if you
1607 * wish to install the driver on your local machine."
1609 if (strlen(driver->driverpath)) {
1610 fstrcpy(temp_name, driver->driverpath);
1611 slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
1614 if (strlen(driver->datafile)) {
1615 fstrcpy(temp_name, driver->datafile);
1616 slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
1619 if (strlen(driver->configfile)) {
1620 fstrcpy(temp_name, driver->configfile);
1621 slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
1624 if (strlen(driver->helpfile)) {
1625 fstrcpy(temp_name, driver->helpfile);
1626 slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
1629 if (driver->dependentfiles) {
1630 for (i=0; *driver->dependentfiles[i]; i++) {
1631 fstrcpy(temp_name, driver->dependentfiles[i]);
1632 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
1636 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1637 dos_to_unix(key); /* Convert key to unix-codepage */
1639 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1641 buf = NULL;
1642 len = buflen = 0;
1644 again:
1645 len = 0;
1646 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1647 driver->cversion,
1648 driver->name,
1649 driver->environment,
1650 driver->driverpath,
1651 driver->datafile,
1652 driver->configfile,
1653 driver->helpfile,
1654 driver->monitorname,
1655 driver->defaultdatatype);
1657 if (driver->dependentfiles) {
1658 for (i=0; *driver->dependentfiles[i]; i++) {
1659 len += tdb_pack(buf+len, buflen-len, "f",
1660 driver->dependentfiles[i]);
1664 if (len != buflen) {
1665 char *tb;
1667 tb = (char *)Realloc(buf, len);
1668 if (!tb) {
1669 DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
1670 ret = -1;
1671 goto done;
1673 else buf = tb;
1674 buflen = len;
1675 goto again;
1679 kbuf.dptr = key;
1680 kbuf.dsize = strlen(key)+1;
1681 dbuf.dptr = buf;
1682 dbuf.dsize = len;
1684 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
1686 done:
1687 if (ret)
1688 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1690 SAFE_FREE(buf);
1691 return ret;
1694 /****************************************************************************
1695 ****************************************************************************/
1696 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1698 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1700 ZERO_STRUCT(info3);
1701 info3.cversion = driver->version;
1702 fstrcpy(info3.name,driver->name);
1703 fstrcpy(info3.environment,driver->environment);
1704 fstrcpy(info3.driverpath,driver->driverpath);
1705 fstrcpy(info3.datafile,driver->datafile);
1706 fstrcpy(info3.configfile,driver->configfile);
1707 fstrcpy(info3.helpfile,driver->helpfile);
1708 fstrcpy(info3.monitorname,driver->monitorname);
1709 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1710 info3.dependentfiles = driver->dependentfiles;
1712 return add_a_printer_driver_3(&info3);
1716 /****************************************************************************
1717 ****************************************************************************/
1718 static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1720 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1722 ZERO_STRUCT(info);
1724 fstrcpy(info.name, in_prt);
1725 fstrcpy(info.defaultdatatype, "RAW");
1727 fstrcpy(info.driverpath, "");
1728 fstrcpy(info.datafile, "");
1729 fstrcpy(info.configfile, "");
1730 fstrcpy(info.helpfile, "");
1732 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1733 return WERR_NOMEM;
1735 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1736 fstrcpy(info.dependentfiles[0], "");
1738 *info_ptr = memdup(&info, sizeof(info));
1740 return WERR_OK;
1743 /****************************************************************************
1744 ****************************************************************************/
1745 static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1747 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1748 TDB_DATA kbuf, dbuf;
1749 fstring architecture;
1750 int len = 0;
1751 int i;
1752 pstring key;
1754 ZERO_STRUCT(driver);
1756 get_short_archi(architecture, in_arch);
1758 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1760 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1762 kbuf.dptr = key;
1763 kbuf.dsize = strlen(key)+1;
1765 dbuf = tdb_fetch(tdb_drivers, kbuf);
1766 #if 0
1767 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1768 #else
1769 if (!dbuf.dptr) return WERR_ACCESS_DENIED;
1770 #endif
1771 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1772 &driver.cversion,
1773 driver.name,
1774 driver.environment,
1775 driver.driverpath,
1776 driver.datafile,
1777 driver.configfile,
1778 driver.helpfile,
1779 driver.monitorname,
1780 driver.defaultdatatype);
1782 i=0;
1783 while (len < dbuf.dsize) {
1784 fstring *tddfs;
1786 tddfs = (fstring *)Realloc(driver.dependentfiles,
1787 sizeof(fstring)*(i+2));
1788 if (tddfs == NULL) {
1789 DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
1790 break;
1792 else driver.dependentfiles = tddfs;
1794 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1795 &driver.dependentfiles[i]);
1796 i++;
1798 if (driver.dependentfiles != NULL)
1799 fstrcpy(driver.dependentfiles[i], "");
1801 SAFE_FREE(dbuf.dptr);
1803 if (len != dbuf.dsize) {
1804 SAFE_FREE(driver.dependentfiles);
1806 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1809 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1811 return WERR_OK;
1814 /****************************************************************************
1815 ****************************************************************************/
1816 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1818 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1819 TDB_DATA kbuf;
1820 pstring key;
1821 int i;
1822 line[0] = '\0';
1824 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1825 DEBUG(10,("driver key: [%s]\n", key));
1827 kbuf.dptr = key;
1828 kbuf.dsize = strlen(key)+1;
1829 if (!tdb_exists(tdb_drivers, kbuf))
1830 return False;
1832 ZERO_STRUCT(info3);
1833 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1835 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1836 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1837 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1838 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1839 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1840 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1841 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1843 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1844 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1845 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1847 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1848 trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
1849 pstrcat(line, info3->driverpath);
1850 pstrcat(line, ":");
1851 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1852 pstrcat(line, info3->datafile);
1853 pstrcat(line, ":");
1854 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1855 pstrcat(line, info3->helpfile);
1856 pstrcat(line, ":");
1857 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1858 pstrcat(line, info3->monitorname);
1859 pstrcat(line, ":");
1860 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1861 pstrcat(line, ":");
1863 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1864 if (i)
1865 pstrcat(line, ","); /* don't end in a "," */
1866 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1867 pstrcat(line, info3->dependentfiles[i]);
1870 SAFE_FREE(info3);
1872 return True;
1875 /****************************************************************************
1876 Debugging function, dump at level 6 the struct in the logs.
1877 ****************************************************************************/
1879 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1881 uint32 result;
1882 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1883 int i;
1885 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1887 switch (level)
1889 case 3:
1891 if (driver.info_3 == NULL)
1892 result=5;
1893 else {
1894 info3=driver.info_3;
1896 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1897 DEBUGADD(106,("name:[%s]\n", info3->name));
1898 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1899 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1900 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1901 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1902 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1903 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1904 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1906 for (i=0; info3->dependentfiles &&
1907 *info3->dependentfiles[i]; i++) {
1908 DEBUGADD(106,("dependentfile:[%s]\n",
1909 info3->dependentfiles[i]));
1911 result=0;
1913 break;
1915 default:
1916 DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
1917 result=1;
1918 break;
1921 return result;
1924 /****************************************************************************
1925 ****************************************************************************/
1926 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1928 int len = 0;
1930 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1932 if (!nt_devmode) return len;
1934 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1935 nt_devmode->devicename,
1936 nt_devmode->formname,
1938 nt_devmode->specversion,
1939 nt_devmode->driverversion,
1940 nt_devmode->size,
1941 nt_devmode->driverextra,
1942 nt_devmode->orientation,
1943 nt_devmode->papersize,
1944 nt_devmode->paperlength,
1945 nt_devmode->paperwidth,
1946 nt_devmode->scale,
1947 nt_devmode->copies,
1948 nt_devmode->defaultsource,
1949 nt_devmode->printquality,
1950 nt_devmode->color,
1951 nt_devmode->duplex,
1952 nt_devmode->yresolution,
1953 nt_devmode->ttoption,
1954 nt_devmode->collate,
1955 nt_devmode->logpixels,
1957 nt_devmode->fields,
1958 nt_devmode->bitsperpel,
1959 nt_devmode->pelswidth,
1960 nt_devmode->pelsheight,
1961 nt_devmode->displayflags,
1962 nt_devmode->displayfrequency,
1963 nt_devmode->icmmethod,
1964 nt_devmode->icmintent,
1965 nt_devmode->mediatype,
1966 nt_devmode->dithertype,
1967 nt_devmode->reserved1,
1968 nt_devmode->reserved2,
1969 nt_devmode->panningwidth,
1970 nt_devmode->panningheight,
1971 nt_devmode->private);
1974 if (nt_devmode->private) {
1975 len += tdb_pack(buf+len, buflen-len, "B",
1976 nt_devmode->driverextra,
1977 nt_devmode->private);
1980 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1982 return len;
1985 /****************************************************************************
1986 ****************************************************************************/
1987 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1989 int len = 0;
1991 while (param != NULL) {
1992 len += tdb_pack(buf+len, buflen-len, "pfdB",
1993 param,
1994 param->value,
1995 param->type,
1996 param->data_len,
1997 param->data);
1998 param=param->next;
2001 len += tdb_pack(buf+len, buflen-len, "p", param);
2003 return len;
2007 /****************************************************************************
2008 Delete a printer - this just deletes the printer info file, any open
2009 handles are not affected.
2010 ****************************************************************************/
2012 uint32 del_a_printer(char *sharename)
2014 pstring key;
2015 TDB_DATA kbuf;
2017 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2018 dos_to_unix(key); /* Convert key to unix-codepage */
2020 kbuf.dptr=key;
2021 kbuf.dsize=strlen(key)+1;
2023 tdb_delete(tdb_printers, kbuf);
2024 return 0;
2027 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
2028 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
2029 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
2030 /****************************************************************************
2031 ****************************************************************************/
2032 static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
2034 pstring key;
2035 char *buf;
2036 int buflen, len;
2037 WERROR ret;
2038 TDB_DATA kbuf, dbuf;
2041 * in addprinter: no servername and the printer is the name
2042 * in setprinter: servername is \\server
2043 * and printer is \\server\\printer
2045 * Samba manages only local printers.
2046 * we currently don't support things like path=\\other_server\printer
2049 if (info->servername[0]!='\0') {
2050 trim_string(info->printername, info->servername, NULL);
2051 trim_string(info->printername, "\\", NULL);
2052 info->servername[0]='\0';
2056 * JFM: one day I'll forget.
2057 * below that's info->portname because that's the SAMBA sharename
2058 * and I made NT 'thinks' it's the portname
2059 * the info->sharename is the thing you can name when you add a printer
2060 * that's the short-name when you create shared printer for 95/98
2061 * So I've made a limitation in SAMBA: you can only have 1 printer model
2062 * behind a SAMBA share.
2065 buf = NULL;
2066 buflen = 0;
2068 again:
2069 len = 0;
2070 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
2071 info->attributes,
2072 info->priority,
2073 info->default_priority,
2074 info->starttime,
2075 info->untiltime,
2076 info->status,
2077 info->cjobs,
2078 info->averageppm,
2079 info->changeid,
2080 info->c_setprinter,
2081 info->setuptime,
2082 info->servername,
2083 info->printername,
2084 info->sharename,
2085 info->portname,
2086 info->drivername,
2087 info->comment,
2088 info->location,
2089 info->sepfile,
2090 info->printprocessor,
2091 info->datatype,
2092 info->parameters);
2094 len += pack_devicemode(info->devmode, buf+len, buflen-len);
2096 len += pack_specifics(info->specific, buf+len, buflen-len);
2098 if (buflen != len) {
2099 char *tb;
2101 tb = (char *)Realloc(buf, len);
2102 if (!tb) {
2103 DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
2104 ret = WERR_NOMEM;
2105 goto done;
2107 else buf = tb;
2108 buflen = len;
2109 goto again;
2113 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, info->sharename);
2114 dos_to_unix(key); /* Convert key to unix-codepage */
2116 kbuf.dptr = key;
2117 kbuf.dsize = strlen(key)+1;
2118 dbuf.dptr = buf;
2119 dbuf.dsize = len;
2121 ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
2123 done:
2124 if (!W_ERROR_IS_OK(ret))
2125 DEBUG(8, ("error updating printer to tdb on disk\n"));
2127 SAFE_FREE(buf);
2129 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
2130 info->sharename, info->drivername, info->portname, len));
2132 return ret;
2136 /****************************************************************************
2137 ****************************************************************************/
2138 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
2140 NT_PRINTER_PARAM *current;
2142 DEBUG(108,("add_a_specific_param\n"));
2144 (*param)->next=NULL;
2146 if (info_2->specific == NULL)
2148 info_2->specific=*param;
2150 else
2152 current=info_2->specific;
2153 while (current->next != NULL) {
2154 current=current->next;
2156 current->next=*param;
2159 *param = NULL;
2162 /****************************************************************************
2163 ****************************************************************************/
2164 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
2166 NT_PRINTER_PARAM *current;
2167 NT_PRINTER_PARAM *previous;
2169 current=info_2->specific;
2170 previous=current;
2172 if (current==NULL) return (False);
2174 if ( !strcmp(current->value, param->value) &&
2175 (strlen(current->value)==strlen(param->value)) ) {
2176 DEBUG(109,("deleting first value\n"));
2177 info_2->specific=current->next;
2178 SAFE_FREE(current->data);
2179 SAFE_FREE(current);
2180 DEBUG(109,("deleted first value\n"));
2181 return (True);
2184 current=previous->next;
2186 while ( current!=NULL ) {
2187 if (!strcmp(current->value, param->value) &&
2188 strlen(current->value)==strlen(param->value) ) {
2189 DEBUG(109,("deleting current value\n"));
2190 previous->next=current->next;
2191 SAFE_FREE(current->data);
2192 SAFE_FREE(current);
2193 DEBUG(109,("deleted current value\n"));
2194 return(True);
2197 previous=previous->next;
2198 current=current->next;
2200 return (False);
2203 /****************************************************************************
2204 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
2205 ****************************************************************************/
2206 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
2208 NT_PRINTER_PARAM *param = *param_ptr;
2210 if(param == NULL)
2211 return;
2213 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
2215 SAFE_FREE(param->data);
2216 SAFE_FREE(*param_ptr);
2219 /****************************************************************************
2220 Malloc and return an NT devicemode.
2221 ****************************************************************************/
2223 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
2226 char adevice[32];
2227 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
2229 if (nt_devmode == NULL) {
2230 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
2231 return NULL;
2234 ZERO_STRUCTP(nt_devmode);
2236 safe_strcpy(adevice, default_devicename, sizeof(adevice));
2237 fstrcpy(nt_devmode->devicename, adevice);
2239 fstrcpy(nt_devmode->formname, "Letter");
2241 nt_devmode->specversion = 0x0401;
2242 nt_devmode->driverversion = 0x0400;
2243 nt_devmode->size = 0x00DC;
2244 nt_devmode->driverextra = 0x0000;
2245 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
2246 DEFAULTSOURCE | COPIES | SCALE |
2247 PAPERSIZE | ORIENTATION;
2248 nt_devmode->orientation = 1;
2249 nt_devmode->papersize = PAPER_LETTER;
2250 nt_devmode->paperlength = 0;
2251 nt_devmode->paperwidth = 0;
2252 nt_devmode->scale = 0x64;
2253 nt_devmode->copies = 1;
2254 nt_devmode->defaultsource = BIN_FORMSOURCE;
2255 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
2256 nt_devmode->color = COLOR_MONOCHROME;
2257 nt_devmode->duplex = DUP_SIMPLEX;
2258 nt_devmode->yresolution = 0;
2259 nt_devmode->ttoption = TT_SUBDEV;
2260 nt_devmode->collate = COLLATE_FALSE;
2261 nt_devmode->icmmethod = 0;
2262 nt_devmode->icmintent = 0;
2263 nt_devmode->mediatype = 0;
2264 nt_devmode->dithertype = 0;
2266 /* non utilisés par un driver d'imprimante */
2267 nt_devmode->logpixels = 0;
2268 nt_devmode->bitsperpel = 0;
2269 nt_devmode->pelswidth = 0;
2270 nt_devmode->pelsheight = 0;
2271 nt_devmode->displayflags = 0;
2272 nt_devmode->displayfrequency = 0;
2273 nt_devmode->reserved1 = 0;
2274 nt_devmode->reserved2 = 0;
2275 nt_devmode->panningwidth = 0;
2276 nt_devmode->panningheight = 0;
2278 nt_devmode->private = NULL;
2279 return nt_devmode;
2282 /****************************************************************************
2283 Deepcopy an NT devicemode.
2284 ****************************************************************************/
2286 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
2288 NT_DEVICEMODE *new_nt_devicemode = NULL;
2290 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
2291 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2292 return NULL;
2295 new_nt_devicemode->private = NULL;
2296 if (nt_devicemode->private != NULL) {
2297 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
2298 SAFE_FREE(new_nt_devicemode);
2299 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
2300 return NULL;
2304 return new_nt_devicemode;
2307 /****************************************************************************
2308 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
2309 ****************************************************************************/
2311 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
2313 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
2315 if(nt_devmode == NULL)
2316 return;
2318 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2320 SAFE_FREE(nt_devmode->private);
2321 SAFE_FREE(*devmode_ptr);
2324 /****************************************************************************
2325 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2326 ****************************************************************************/
2327 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2329 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2330 NT_PRINTER_PARAM *param_ptr;
2332 if(info == NULL)
2333 return;
2335 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2337 free_nt_devicemode(&info->devmode);
2339 for(param_ptr = info->specific; param_ptr; ) {
2340 NT_PRINTER_PARAM *tofree = param_ptr;
2342 param_ptr = param_ptr->next;
2343 free_nt_printer_param(&tofree);
2346 SAFE_FREE(*info_ptr);
2350 /****************************************************************************
2351 ****************************************************************************/
2352 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2354 int len = 0;
2355 int extra_len = 0;
2356 NT_DEVICEMODE devmode;
2358 ZERO_STRUCT(devmode);
2360 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2362 if (!*nt_devmode) return len;
2364 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2365 devmode.devicename,
2366 devmode.formname,
2368 &devmode.specversion,
2369 &devmode.driverversion,
2370 &devmode.size,
2371 &devmode.driverextra,
2372 &devmode.orientation,
2373 &devmode.papersize,
2374 &devmode.paperlength,
2375 &devmode.paperwidth,
2376 &devmode.scale,
2377 &devmode.copies,
2378 &devmode.defaultsource,
2379 &devmode.printquality,
2380 &devmode.color,
2381 &devmode.duplex,
2382 &devmode.yresolution,
2383 &devmode.ttoption,
2384 &devmode.collate,
2385 &devmode.logpixels,
2387 &devmode.fields,
2388 &devmode.bitsperpel,
2389 &devmode.pelswidth,
2390 &devmode.pelsheight,
2391 &devmode.displayflags,
2392 &devmode.displayfrequency,
2393 &devmode.icmmethod,
2394 &devmode.icmintent,
2395 &devmode.mediatype,
2396 &devmode.dithertype,
2397 &devmode.reserved1,
2398 &devmode.reserved2,
2399 &devmode.panningwidth,
2400 &devmode.panningheight,
2401 &devmode.private);
2403 if (devmode.private) {
2404 /* the len in tdb_unpack is an int value and
2405 * devmode.driverextra is only a short
2407 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2408 devmode.driverextra=(uint16)extra_len;
2410 /* check to catch an invalid TDB entry so we don't segfault */
2411 if (devmode.driverextra == 0) {
2412 devmode.private = NULL;
2416 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2418 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2419 if (devmode.private)
2420 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2422 return len;
2425 /****************************************************************************
2426 ****************************************************************************/
2427 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2429 int len = 0;
2430 NT_PRINTER_PARAM param, *p;
2432 *list = NULL;
2434 while (1) {
2435 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2436 if (!p) break;
2438 len += tdb_unpack(buf+len, buflen-len, "fdB",
2439 param.value,
2440 &param.type,
2441 &param.data_len,
2442 &param.data);
2443 param.next = *list;
2444 *list = memdup(&param, sizeof(param));
2446 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2449 return len;
2452 static void map_to_os2_driver(fstring drivername)
2454 static BOOL initialised=False;
2455 static fstring last_from,last_to;
2456 char *mapfile = lp_os2_driver_map();
2457 char **lines = NULL;
2458 int numlines = 0;
2459 int i;
2461 if (!strlen(drivername))
2462 return;
2464 if (!*mapfile)
2465 return;
2467 if (!initialised) {
2468 *last_from = *last_to = 0;
2469 initialised = True;
2472 if (strequal(drivername,last_from)) {
2473 DEBUG(3,("Mapped Windows driver %s to OS/2 driver %s\n",drivername,last_to));
2474 fstrcpy(drivername,last_to);
2475 return;
2478 lines = file_lines_load(mapfile, &numlines, True);
2479 if (numlines == 0) {
2480 DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
2481 return;
2484 DEBUG(4,("Scanning OS/2 driver map %s\n",mapfile));
2486 for( i = 0; i < numlines; i++) {
2487 char *nt_name = lines[i];
2488 char *os2_name = strchr(nt_name,'=');
2490 if (!os2_name)
2491 continue;
2493 *os2_name++ = 0;
2495 while (isspace(*nt_name))
2496 nt_name++;
2498 if (!*nt_name || strchr("#;",*nt_name))
2499 continue;
2502 int l = strlen(nt_name);
2503 while (l && isspace(nt_name[l-1])) {
2504 nt_name[l-1] = 0;
2505 l--;
2509 while (isspace(*os2_name))
2510 os2_name++;
2513 int l = strlen(os2_name);
2514 while (l && isspace(os2_name[l-1])) {
2515 os2_name[l-1] = 0;
2516 l--;
2520 if (strequal(nt_name,drivername)) {
2521 DEBUG(3,("Mapped windows driver %s to os2 driver%s\n",drivername,os2_name));
2522 fstrcpy(last_from,drivername);
2523 fstrcpy(last_to,os2_name);
2524 fstrcpy(drivername,os2_name);
2525 file_lines_free(lines);
2526 return;
2530 file_lines_free(lines);
2533 /****************************************************************************
2534 get a default printer info 2 struct
2535 ****************************************************************************/
2536 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2538 int snum;
2539 NT_PRINTER_INFO_LEVEL_2 info;
2541 ZERO_STRUCT(info);
2543 snum = lp_servicenumber(sharename);
2545 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2546 slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
2547 get_called_name(), sharename);
2548 fstrcpy(info.sharename, sharename);
2549 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2550 fstrcpy(info.drivername, lp_printerdriver(snum));
2552 /* by setting the driver name to an empty string, a local NT admin
2553 can now run the **local** APW to install a local printer driver
2554 for a Samba shared printer in 2.2. Without this, drivers **must** be
2555 installed on the Samba server for NT clients --jerry */
2556 #if 0 /* JERRY --do not uncomment-- */
2557 if (!*info.drivername)
2558 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2559 #endif
2562 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2564 pstrcpy(info.comment, "");
2565 fstrcpy(info.printprocessor, "winprint");
2566 fstrcpy(info.datatype, "RAW");
2568 info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
2570 info.starttime = 0; /* Minutes since 12:00am GMT */
2571 info.untiltime = 0; /* Minutes since 12:00am GMT */
2572 info.priority = 1;
2573 info.default_priority = 1;
2574 info.setuptime = (uint32)time(NULL);
2577 * I changed this as I think it is better to have a generic
2578 * DEVMODE than to crash Win2k explorer.exe --jerry
2579 * See the HP Deskjet 990c Win2k drivers for an example.
2581 * However the default devmode appears to cause problems
2582 * with the HP CLJ 8500 PCL driver. Hence the addition of
2583 * the "default devmode" parameter --jerry 22/01/2002
2586 if (lp_default_devmode(snum)) {
2587 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2588 goto fail;
2590 else {
2591 info.devmode = NULL;
2594 /* This will get the current RPC talloc context, but we should be
2595 passing this as a parameter... fixme... JRA ! */
2597 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2598 goto fail;
2600 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2601 if (! *info_ptr) {
2602 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2603 goto fail;
2606 return WERR_OK;
2608 fail:
2609 if (info.devmode)
2610 free_nt_devicemode(&info.devmode);
2611 return WERR_ACCESS_DENIED;
2614 /****************************************************************************
2615 ****************************************************************************/
2616 static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2618 pstring key;
2619 NT_PRINTER_INFO_LEVEL_2 info;
2620 int len = 0;
2621 TDB_DATA kbuf, dbuf;
2622 fstring printername;
2624 ZERO_STRUCT(info);
2626 slprintf(key, sizeof(key)-1, "%s%s", PRINTERS_PREFIX, sharename);
2627 dos_to_unix(key); /* Convert key to unix-codepage */
2629 kbuf.dptr = key;
2630 kbuf.dsize = strlen(key)+1;
2632 dbuf = tdb_fetch(tdb_printers, kbuf);
2633 if (!dbuf.dptr)
2634 return get_a_printer_2_default(info_ptr, sharename);
2636 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2637 &info.attributes,
2638 &info.priority,
2639 &info.default_priority,
2640 &info.starttime,
2641 &info.untiltime,
2642 &info.status,
2643 &info.cjobs,
2644 &info.averageppm,
2645 &info.changeid,
2646 &info.c_setprinter,
2647 &info.setuptime,
2648 info.servername,
2649 info.printername,
2650 info.sharename,
2651 info.portname,
2652 info.drivername,
2653 info.comment,
2654 info.location,
2655 info.sepfile,
2656 info.printprocessor,
2657 info.datatype,
2658 info.parameters);
2660 /* Samba has to have shared raw drivers. */
2661 info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
2663 /* Restore the stripped strings. */
2664 slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
2665 slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
2666 info.printername);
2667 fstrcpy(info.printername, printername);
2669 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2672 * Some client drivers freak out if there is a NULL devmode
2673 * (probably the driver is not checking before accessing
2674 * the devmode pointer) --jerry
2676 * See comments in get_a_printer_2_default()
2679 if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
2681 DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
2682 printername));
2683 info.devmode = construct_nt_devicemode(printername);
2686 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2688 /* This will get the current RPC talloc context, but we should be
2689 passing this as a parameter... fixme... JRA ! */
2691 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2693 /* Fix for OS/2 drivers. */
2695 if (get_remote_arch() == RA_OS2)
2696 map_to_os2_driver(info.drivername);
2698 SAFE_FREE(dbuf.dptr);
2699 *info_ptr=memdup(&info, sizeof(info));
2701 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2702 sharename, info.printername, info.drivername));
2704 return WERR_OK;
2707 /****************************************************************************
2708 debugging function, dump at level 6 the struct in the logs
2709 ****************************************************************************/
2710 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2712 uint32 result;
2713 NT_PRINTER_INFO_LEVEL_2 *info2;
2715 DEBUG(106,("Dumping printer at level [%d]\n", level));
2717 switch (level)
2719 case 2:
2721 if (printer.info_2 == NULL)
2722 result=5;
2723 else
2725 info2=printer.info_2;
2727 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2728 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2729 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2730 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2731 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2732 DEBUGADD(106,("status:[%d]\n", info2->status));
2733 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2734 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2735 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2736 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2737 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2739 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2740 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2741 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2742 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2743 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2744 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2745 DEBUGADD(106,("location:[%s]\n", info2->location));
2746 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2747 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2748 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2749 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2750 result=0;
2752 break;
2754 default:
2755 DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
2756 result=1;
2757 break;
2760 return result;
2763 /****************************************************************************
2764 Get the parameters we can substitute in an NT print job.
2765 ****************************************************************************/
2767 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2769 NT_PRINTER_INFO_LEVEL *printer = NULL;
2771 **printername = **sharename = **portname = '\0';
2773 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
2774 return;
2776 fstrcpy(*printername, printer->info_2->printername);
2777 fstrcpy(*sharename, printer->info_2->sharename);
2778 fstrcpy(*portname, printer->info_2->portname);
2780 free_a_printer(&printer, 2);
2783 /****************************************************************************
2784 Update the changeid time.
2785 This is SO NASTY as some drivers need this to change, others need it
2786 static. This value will change every second, and I must hope that this
2787 is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
2788 UTAH ! JRA.
2789 ****************************************************************************/
2791 static uint32 rev_changeid(void)
2793 struct timeval tv;
2795 get_process_uptime(&tv);
2797 #if 1 /* JERRY */
2798 /* Return changeid as msec since spooler restart */
2799 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
2800 #else
2802 * This setting seems to work well but is too untested
2803 * to replace the above calculation. Left in for experiementation
2804 * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
2806 return tv.tv_sec * 10 + tv.tv_usec / 100000;
2807 #endif
2811 * The function below are the high level ones.
2812 * only those ones must be called from the spoolss code.
2813 * JFM.
2816 /****************************************************************************
2817 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2818 ****************************************************************************/
2820 WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2822 WERROR result;
2824 dump_a_printer(printer, level);
2826 switch (level)
2828 case 2:
2831 * Update the changestamp. Emperical tests show that the
2832 * ChangeID is always updated,but c_setprinter is
2833 * global spooler variable (not per printer).
2836 /* ChangeID **must** be increasing over the lifetime
2837 of client's spoolss service in order for the
2838 client's cache to show updates */
2840 printer.info_2->changeid = rev_changeid();
2843 * Because one day someone will ask:
2844 * NT->NT An admin connection to a remote
2845 * printer show changes imeediately in
2846 * the properities dialog
2848 * A non-admin connection will only show the
2849 * changes after viewing the properites page
2850 * 2 times. Seems to be related to a
2851 * race condition in the client between the spooler
2852 * updating the local cache and the Explorer.exe GUI
2853 * actually displaying the properties.
2855 * This is fixed in Win2k. admin/non-admin
2856 * connections both display changes immediately.
2858 * 14/12/01 --jerry
2861 result=update_a_printer_2(printer.info_2);
2862 break;
2864 default:
2865 result=WERR_UNKNOWN_LEVEL;
2866 break;
2869 return result;
2872 /****************************************************************************
2873 Initialize printer devmode & data with previously saved driver init values.
2874 ****************************************************************************/
2876 static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
2878 int len = 0;
2879 pstring key;
2880 TDB_DATA kbuf, dbuf;
2881 NT_PRINTER_PARAM *current;
2882 NT_PRINTER_INFO_LEVEL_2 info;
2885 * Delete any printer data 'specifics' already set. When called for driver
2886 * replace, there will generally be some, but during an add printer, there
2887 * should not be any (if there are delete them).
2889 while ( (current=info_ptr->specific) != NULL ) {
2890 info_ptr->specific=current->next;
2891 SAFE_FREE(current->data);
2892 SAFE_FREE(current);
2895 ZERO_STRUCT(info);
2897 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
2898 dos_to_unix(key); /* Convert key to unix-codepage */
2900 kbuf.dptr = key;
2901 kbuf.dsize = strlen(key)+1;
2903 dbuf = tdb_fetch(tdb_drivers, kbuf);
2904 if (!dbuf.dptr) {
2906 * When changing to a driver that has no init info in the tdb, remove
2907 * the previous drivers init info and leave the new on blank.
2909 free_nt_devicemode(&info_ptr->devmode);
2910 return False;
2914 * Get the saved DEVMODE..
2916 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2919 * The saved DEVMODE contains the devicename from the printer used during
2920 * the initialization save. Change it to reflect the new printer.
2922 ZERO_STRUCT(info.devmode->devicename);
2923 fstrcpy(info.devmode->devicename, info_ptr->printername);
2927 * NT/2k does not change out the entire DeviceMode of a printer
2928 * when changing the driver. Only the driverextra, private, &
2929 * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
2931 * Later e4xamination revealed that Windows NT/2k does reset the
2932 * the printer's device mode, bit **only** when you change a
2933 * property of the device mode such as the page orientation.
2934 * --jerry
2937 #if 1 /* JERRY */
2940 * Bind the saved DEVMODE to the new the printer.
2942 free_nt_devicemode(&info_ptr->devmode);
2943 info_ptr->devmode = info.devmode;
2944 #else
2945 /* copy the entire devmode if we currently don't have one */
2947 if (!info_ptr->devmode) {
2948 DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
2949 info_ptr->devmode = info.devmode;
2951 else {
2952 /* only set the necessary fields */
2954 DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
2955 info.devmode->driverversion, info.devmode->driverextra));
2957 info_ptr->devmode->driverversion = info.devmode->driverversion;
2959 SAFE_FREE(info_ptr->devmode->private);
2960 info_ptr->devmode->private = NULL;
2962 if (info.devmode->driverversion)
2963 info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
2965 free_nt_devicemode(&info.devmode);
2967 #endif
2969 DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
2970 info_ptr->printername, info_ptr->drivername));
2973 * Add the printer data 'specifics' to the new printer
2975 len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
2977 SAFE_FREE(dbuf.dptr);
2979 return True;
2982 /****************************************************************************
2983 Initialize printer devmode & data with previously saved driver init values.
2984 When a printer is created using AddPrinter, the drivername bound to the
2985 printer is used to lookup previously saved driver initialization info, which
2986 is bound to the new printer.
2987 ****************************************************************************/
2989 BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
2991 BOOL result = False;
2993 switch (level)
2995 case 2:
2996 result = set_driver_init_2(printer->info_2);
2997 break;
2999 default:
3000 DEBUG(0,("set_driver_init: Programmer's error! Unknown driver_init level [%d]\n",
3001 level));
3002 break;
3005 return result;
3008 /****************************************************************************
3009 Delete driver init data stored for a specified driver
3010 ****************************************************************************/
3012 BOOL del_driver_init(char *drivername)
3014 pstring key;
3015 TDB_DATA kbuf;
3017 if (!drivername || !*drivername) {
3018 DEBUG(3,("del_driver_init: No drivername specified!\n"));
3019 return False;
3022 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
3023 dos_to_unix(key); /* Convert key to unix-codepage */
3025 kbuf.dptr = key;
3026 kbuf.dsize = strlen(key)+1;
3028 DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
3030 return (tdb_delete(tdb_drivers, kbuf) == 0);
3033 /****************************************************************************
3034 Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
3035 in the tdb. Note: this is different from the driver entry and the printer
3036 entry. There should be a single driver init entry for each driver regardless
3037 of whether it was installed from NT or 2K. Technically, they should be
3038 different, but they work out to the same struct.
3039 ****************************************************************************/
3041 static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info)
3043 pstring key;
3044 char *buf;
3045 int buflen, len, ret;
3046 TDB_DATA kbuf, dbuf;
3048 buf = NULL;
3049 buflen = 0;
3051 again:
3052 len = 0;
3053 len += pack_devicemode(info->devmode, buf+len, buflen-len);
3055 len += pack_specifics(info->specific, buf+len, buflen-len);
3057 if (buflen != len) {
3058 char *tb;
3060 tb = (char *)Realloc(buf, len);
3061 if (!tb) {
3062 DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
3063 ret = -1;
3064 goto done;
3066 else buf = tb;
3067 buflen = len;
3068 goto again;
3071 slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info->drivername);
3072 dos_to_unix(key); /* Convert key to unix-codepage */
3074 kbuf.dptr = key;
3075 kbuf.dsize = strlen(key)+1;
3076 dbuf.dptr = buf;
3077 dbuf.dsize = len;
3079 ret = tdb_store(tdb_drivers, kbuf, dbuf, TDB_REPLACE);
3081 done:
3082 if (ret == -1)
3083 DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
3085 SAFE_FREE(buf);
3087 DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
3088 info->sharename, info->drivername));
3090 return ret;
3093 /****************************************************************************
3094 Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer
3095 ****************************************************************************/
3097 uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
3099 uint32 result;
3101 dump_a_printer(printer, level);
3103 switch (level)
3105 case 2:
3107 result=update_driver_init_2(printer.info_2);
3108 break;
3110 default:
3111 result=1;
3112 break;
3115 return result;
3118 /****************************************************************************
3119 Convert the printer data value, a REG_BINARY array, into an initialization
3120 DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
3121 got to keep the endians happy :).
3122 ****************************************************************************/
3124 static BOOL convert_driver_init(NT_PRINTER_PARAM *param, TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode)
3126 BOOL result = False;
3127 prs_struct ps;
3128 DEVICEMODE devmode;
3130 ZERO_STRUCT(devmode);
3132 prs_init(&ps, 0, ctx, UNMARSHALL);
3133 ps.data_p = (char *)param->data;
3134 ps.buffer_size = param->data_len;
3136 if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
3137 result = convert_devicemode("", &devmode, &nt_devmode);
3138 else
3139 DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
3141 return result;
3144 /****************************************************************************
3145 Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
3147 1. Use the driver's config DLL to this UNC printername and:
3148 a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
3149 b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
3150 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
3152 The last step triggers saving the "driver initialization" information for
3153 this printer into the tdb. Later, new printers that use this driver will
3154 have this initialization information bound to them. This simulates the
3155 driver initialization, as if it had run on the Samba server (as it would
3156 have done on NT).
3158 The Win32 client side code requirement sucks! But until we can run arbitrary
3159 Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
3161 It would have been easier to use SetPrinter because all the UNMARSHALLING of
3162 the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
3163 about it and you will realize why. JRR 010720
3164 ****************************************************************************/
3166 static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
3168 WERROR status = WERR_OK;
3169 TALLOC_CTX *ctx = NULL;
3170 NT_DEVICEMODE *nt_devmode = NULL;
3171 NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
3174 * When the DEVMODE is already set on the printer, don't try to unpack it.
3177 if (!printer->info_2->devmode && param->data_len) {
3179 * Set devmode on printer info, so entire printer initialization can be
3180 * saved to tdb.
3183 if ((ctx = talloc_init()) == NULL)
3184 return WERR_NOMEM;
3186 if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
3187 status = WERR_NOMEM;
3188 goto done;
3191 ZERO_STRUCTP(nt_devmode);
3194 * The DEVMODE is held in the 'data' component of the param in raw binary.
3195 * Convert it to to a devmode structure
3197 if (!convert_driver_init(param, ctx, nt_devmode)) {
3198 DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
3199 status = WERR_INVALID_PARAM;
3200 goto done;
3203 printer->info_2->devmode = nt_devmode;
3207 * Pack up and add (or update) the DEVMODE and any current printer data to
3208 * a 'driver init' element in the tdb
3212 if (update_driver_init(*printer, 2)!=0) {
3213 DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
3214 status = WERR_NOMEM;
3215 goto done;
3219 * If driver initialization info was successfully saved, set the current
3220 * printer to match it. This allows initialization of the current printer
3221 * as well as the driver.
3223 status = mod_a_printer(*printer, 2);
3224 if (!W_ERROR_IS_OK(status)) {
3225 DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
3226 printer->info_2->printername));
3229 #if 0 /* JERRY */
3230 srv_spoolss_sendnotify(p, handle);
3231 #endif
3233 done:
3234 talloc_destroy(ctx);
3235 if (nt_devmode)
3236 SAFE_FREE(nt_devmode->private);
3237 SAFE_FREE(nt_devmode);
3238 printer->info_2->devmode = tmp_devmode;
3240 return status;
3243 /****************************************************************************
3244 Update the driver init info (DEVMODE and specifics) for a printer
3245 ****************************************************************************/
3247 WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
3249 WERROR status = WERR_OK;
3251 switch (level)
3253 case 2:
3255 status=save_driver_init_2(printer, param);
3256 break;
3258 default:
3259 status=WERR_UNKNOWN_LEVEL;
3260 break;
3263 return status;
3266 /****************************************************************************
3267 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
3268 ****************************************************************************/
3270 WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
3272 WERROR result;
3273 NT_PRINTER_INFO_LEVEL *printer = NULL;
3275 *pp_printer = NULL;
3277 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
3279 switch (level)
3281 case 2:
3283 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
3284 DEBUG(0,("get_a_printer: malloc fail.\n"));
3285 return WERR_NOMEM;
3287 ZERO_STRUCTP(printer);
3288 result=get_a_printer_2(&printer->info_2, sharename);
3289 if (W_ERROR_IS_OK(result)) {
3290 dump_a_printer(*printer, level);
3291 *pp_printer = printer;
3292 } else {
3293 SAFE_FREE(printer);
3295 break;
3297 default:
3298 result=WERR_UNKNOWN_LEVEL;
3299 break;
3302 DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
3304 return result;
3307 /****************************************************************************
3308 Deletes a NT_PRINTER_INFO_LEVEL struct.
3309 ****************************************************************************/
3311 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
3313 uint32 result;
3314 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
3316 DEBUG(104,("freeing a printer at level [%d]\n", level));
3318 if (printer == NULL)
3319 return 0;
3321 switch (level)
3323 case 2:
3325 if (printer->info_2 != NULL)
3327 free_nt_printer_info_level_2(&printer->info_2);
3328 result=0;
3330 else
3332 result=4;
3334 break;
3336 default:
3337 result=1;
3338 break;
3341 SAFE_FREE(*pp_printer);
3342 return result;
3345 /****************************************************************************
3346 ****************************************************************************/
3347 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3349 uint32 result;
3350 DEBUG(104,("adding a printer at level [%d]\n", level));
3351 dump_a_printer_driver(driver, level);
3353 switch (level)
3355 case 3:
3357 result=add_a_printer_driver_3(driver.info_3);
3358 break;
3361 case 6:
3363 result=add_a_printer_driver_6(driver.info_6);
3364 break;
3366 default:
3367 result=1;
3368 break;
3371 return result;
3373 /****************************************************************************
3374 ****************************************************************************/
3375 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
3376 fstring printername, fstring architecture, uint32 version)
3378 WERROR result;
3380 switch (level)
3382 case 3:
3384 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
3385 break;
3387 default:
3388 result=W_ERROR(1);
3389 break;
3392 if (W_ERROR_IS_OK(result))
3393 dump_a_printer_driver(*driver, level);
3394 return result;
3397 /****************************************************************************
3398 ****************************************************************************/
3399 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
3401 uint32 result;
3403 switch (level)
3405 case 3:
3407 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
3408 if (driver.info_3 != NULL)
3410 info3=driver.info_3;
3411 SAFE_FREE(info3->dependentfiles);
3412 ZERO_STRUCTP(info3);
3413 SAFE_FREE(info3);
3414 result=0;
3416 else
3418 result=4;
3420 break;
3422 case 6:
3424 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
3425 if (driver.info_6 != NULL)
3427 info6=driver.info_6;
3428 SAFE_FREE(info6->dependentfiles);
3429 SAFE_FREE(info6->previousnames);
3430 ZERO_STRUCTP(info6);
3431 SAFE_FREE(info6);
3432 result=0;
3434 else
3436 result=4;
3438 break;
3440 default:
3441 result=1;
3442 break;
3444 return result;
3448 /****************************************************************************
3449 Determine whether or not a particular driver is currently assigned
3450 to a printer
3451 ****************************************************************************/
3452 BOOL printer_driver_in_use (char *arch, char *driver)
3454 TDB_DATA kbuf, newkey, dbuf;
3455 NT_PRINTER_INFO_LEVEL_2 info;
3456 int ret;
3458 if (!tdb_printers)
3459 if (!nt_printing_init())
3460 return False;
3462 DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
3464 /* loop through the printers.tdb and check for the drivername */
3465 for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
3466 newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey)
3469 dbuf = tdb_fetch(tdb_printers, kbuf);
3470 if (!dbuf.dptr)
3471 continue;
3473 if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0)
3474 continue;
3476 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
3477 &info.attributes,
3478 &info.priority,
3479 &info.default_priority,
3480 &info.starttime,
3481 &info.untiltime,
3482 &info.status,
3483 &info.cjobs,
3484 &info.averageppm,
3485 &info.changeid,
3486 &info.c_setprinter,
3487 &info.setuptime,
3488 info.servername,
3489 info.printername,
3490 info.sharename,
3491 info.portname,
3492 info.drivername,
3493 info.comment,
3494 info.location,
3495 info.sepfile,
3496 info.printprocessor,
3497 info.datatype,
3498 info.parameters);
3500 SAFE_FREE(dbuf.dptr);
3502 if (ret == -1) {
3503 DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
3504 info.printername));
3505 continue;
3508 DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
3509 info.printername, info.drivername));
3511 if (strcmp(info.drivername, driver) == 0)
3513 DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
3514 info.printername, driver));
3515 return True;
3518 DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
3522 /* report that the driver is in use by default */
3523 return False;
3526 /****************************************************************************
3527 Remove a printer driver from the TDB. This assumes that the the driver was
3528 previously looked up.
3529 ***************************************************************************/
3530 WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
3532 pstring key;
3533 fstring arch;
3534 TDB_DATA kbuf;
3537 get_short_archi(arch, i->environment);
3538 slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
3539 arch, i->cversion, i->name);
3540 DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
3542 kbuf.dptr=key;
3543 kbuf.dsize=strlen(key)+1;
3545 if (tdb_delete(tdb_drivers, kbuf) == -1) {
3546 DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
3547 return WERR_ACCESS_DENIED;
3550 DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
3551 i->name));
3553 return WERR_OK;
3555 /****************************************************************************
3556 ****************************************************************************/
3557 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
3558 fstring value, uint8 **data, uint32 *type, uint32 *len)
3560 /* right now that's enough ! */
3561 NT_PRINTER_PARAM *param;
3562 int i=0;
3564 param=printer.info_2->specific;
3566 while (param != NULL && i < param_index) {
3567 param=param->next;
3568 i++;
3571 if (param == NULL)
3572 return False;
3574 /* exited because it exist */
3575 *type=param->type;
3576 StrnCpy(value, param->value, sizeof(fstring)-1);
3577 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3578 if(*data == NULL)
3579 return False;
3580 ZERO_STRUCTP(*data);
3581 memcpy(*data, param->data, param->data_len);
3582 *len=param->data_len;
3583 return True;
3586 /****************************************************************************
3587 ****************************************************************************/
3588 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
3589 fstring value, uint8 **data, uint32 *type, uint32 *len)
3591 /* right now that's enough ! */
3592 NT_PRINTER_PARAM *param;
3594 DEBUG(10, ("get_specific_param\n"));
3596 param=printer.info_2->specific;
3598 while (param != NULL)
3600 #if 1 /* JRA - I think this should be case insensitive.... */
3601 if ( strequal(value, param->value)
3602 #else
3603 if ( !strcmp(value, param->value)
3604 #endif
3605 && strlen(value)==strlen(param->value))
3606 break;
3608 param=param->next;
3611 if (param != NULL)
3613 DEBUGADD(10, ("get_specific_param: found one param\n"));
3614 /* exited because it exist */
3615 *type=param->type;
3617 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
3618 if(*data == NULL)
3619 return False;
3620 memcpy(*data, param->data, param->data_len);
3621 *len=param->data_len;
3623 DEBUGADD(10, ("get_specific_param: exit true\n"));
3624 return (True);
3626 DEBUGADD(10, ("get_specific_param: exit false\n"));
3627 return (False);
3630 /****************************************************************************
3631 Store a security desc for a printer.
3632 ****************************************************************************/
3634 WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
3636 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3637 SEC_DESC_BUF *old_secdesc_ctr = NULL;
3638 prs_struct ps;
3639 TALLOC_CTX *mem_ctx = NULL;
3640 fstring key;
3641 WERROR status;
3643 mem_ctx = talloc_init();
3644 if (mem_ctx == NULL)
3645 return WERR_NOMEM;
3647 /* The old owner and group sids of the security descriptor are not
3648 present when new ACEs are added or removed by changing printer
3649 permissions through NT. If they are NULL in the new security
3650 descriptor then copy them over from the old one. */
3652 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
3653 DOM_SID *owner_sid, *group_sid;
3654 SEC_ACL *dacl, *sacl;
3655 SEC_DESC *psd = NULL;
3656 size_t size;
3658 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
3660 /* Pick out correct owner and group sids */
3662 owner_sid = secdesc_ctr->sec->owner_sid ?
3663 secdesc_ctr->sec->owner_sid :
3664 old_secdesc_ctr->sec->owner_sid;
3666 group_sid = secdesc_ctr->sec->grp_sid ?
3667 secdesc_ctr->sec->grp_sid :
3668 old_secdesc_ctr->sec->grp_sid;
3670 dacl = secdesc_ctr->sec->dacl ?
3671 secdesc_ctr->sec->dacl :
3672 old_secdesc_ctr->sec->dacl;
3674 sacl = secdesc_ctr->sec->sacl ?
3675 secdesc_ctr->sec->sacl :
3676 old_secdesc_ctr->sec->sacl;
3678 /* Make a deep copy of the security descriptor */
3680 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
3681 owner_sid, group_sid,
3682 sacl,
3683 dacl,
3684 &size);
3686 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
3689 if (!new_secdesc_ctr) {
3690 new_secdesc_ctr = secdesc_ctr;
3693 /* Store the security descriptor in a tdb */
3695 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
3696 sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL);
3698 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
3699 &ps, 1)) {
3700 status = WERR_BADFUNC;
3701 goto out;
3704 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3706 if (tdb_prs_store(tdb_printers, key, &ps)==0) {
3707 status = WERR_OK;
3708 } else {
3709 DEBUG(1,("Failed to store secdesc for %s\n", printername));
3710 status = WERR_BADFUNC;
3713 /* Free malloc'ed memory */
3715 out:
3717 prs_mem_free(&ps);
3718 if (mem_ctx)
3719 talloc_destroy(mem_ctx);
3720 return status;
3723 /****************************************************************************
3724 Construct a default security descriptor buffer for a printer.
3725 ****************************************************************************/
3727 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
3729 extern DOM_SID global_sam_sid;
3730 SEC_ACE ace[3];
3731 SEC_ACCESS sa;
3732 SEC_ACL *psa = NULL;
3733 SEC_DESC_BUF *sdb = NULL;
3734 SEC_DESC *psd = NULL;
3735 DOM_SID owner_sid;
3736 size_t sd_size;
3737 enum SID_NAME_USE name_type;
3738 fstring dos_domain;
3740 /* Create an ACE where Everyone is allowed to print */
3742 init_sec_access(&sa, PRINTER_ACE_PRINT);
3743 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
3744 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3746 /* Make the security descriptor owned by the Administrators group
3747 on the PDC of the domain. */
3749 /* Note that for hysterical raisins, the argument to
3750 secrets_fetch_domain_sid() must be in dos codepage format.
3751 Aargh! */
3753 fstrcpy(dos_domain, lp_workgroup());
3754 unix_to_dos(dos_domain);
3756 if (secrets_fetch_domain_sid(dos_domain, &owner_sid)) {
3757 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3758 } else {
3760 /* Backup plan - make printer owned by admins or root.
3761 This should emulate a lanman printer as security
3762 settings can't be changed. */
3764 if (!lookup_name("root", &owner_sid, &name_type)) {
3765 sid_copy(&owner_sid, &global_sam_sid);
3766 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3770 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3771 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3772 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
3773 SEC_ACE_FLAG_INHERIT_ONLY);
3775 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
3776 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
3777 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
3779 /* The ACL revision number in rpc_secdesc.h differs from the one
3780 created by NT when setting ACE entries in printer
3781 descriptors. NT4 complains about the property being edited by a
3782 NT5 machine. */
3784 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
3785 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
3786 &owner_sid, NULL,
3787 NULL, psa, &sd_size);
3790 if (!psd) {
3791 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
3792 return NULL;
3795 sdb = make_sec_desc_buf(ctx, sd_size, psd);
3797 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
3798 (unsigned int)sd_size));
3800 return sdb;
3803 /****************************************************************************
3804 Get a security desc for a printer.
3805 ****************************************************************************/
3807 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
3809 prs_struct ps;
3810 fstring key;
3811 char *temp;
3813 if ((temp = strchr(printername + 2, '\\'))) {
3814 printername = temp + 1;
3817 /* Fetch security descriptor from tdb */
3819 slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
3821 if (tdb_prs_fetch(tdb_printers, key, &ps, ctx)!=0 ||
3822 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
3824 DEBUG(4,("using default secdesc for %s\n", printername));
3826 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
3827 return False;
3830 /* Save default security descriptor for later */
3832 prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
3833 sizeof(SEC_DESC_BUF), ctx, MARSHALL);
3835 if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
3836 tdb_prs_store(tdb_printers, key, &ps);
3838 prs_mem_free(&ps);
3840 return True;
3843 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
3844 this security descriptor has been created when winbindd was
3845 down. Take ownership of security descriptor. */
3847 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
3848 DOM_SID owner_sid;
3849 enum SID_NAME_USE name_type;
3851 /* Change sd owner to workgroup administrator */
3853 if (winbind_lookup_name(NULL, lp_workgroup(), &owner_sid,
3854 &name_type)) {
3855 SEC_DESC_BUF *new_secdesc_ctr = NULL;
3856 SEC_DESC *psd = NULL;
3857 size_t size;
3859 /* Create new sd */
3861 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
3863 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
3864 &owner_sid,
3865 (*secdesc_ctr)->sec->grp_sid,
3866 (*secdesc_ctr)->sec->sacl,
3867 (*secdesc_ctr)->sec->dacl,
3868 &size);
3870 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
3872 /* Swap with other one */
3874 *secdesc_ctr = new_secdesc_ctr;
3876 /* Set it */
3878 nt_printing_setsec(printername, *secdesc_ctr);
3882 if (DEBUGLEVEL >= 10) {
3883 SEC_ACL *the_acl = (*secdesc_ctr)->sec->dacl;
3884 int i;
3886 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3887 printername, the_acl->num_aces));
3889 for (i = 0; i < the_acl->num_aces; i++) {
3890 fstring sid_str;
3892 sid_to_string(sid_str, &the_acl->ace[i].trustee);
3894 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
3895 the_acl->ace[i].type, the_acl->ace[i].flags,
3896 the_acl->ace[i].info.mask));
3900 prs_mem_free(&ps);
3901 return True;
3904 /* error code:
3905 0: everything OK
3906 1: level not implemented
3907 2: file doesn't exist
3908 3: can't allocate memory
3909 4: can't free memory
3910 5: non existant struct
3914 A printer and a printer driver are 2 different things.
3915 NT manages them separatelly, Samba does the same.
3916 Why ? Simply because it's easier and it makes sense !
3918 Now explanation: You have 3 printers behind your samba server,
3919 2 of them are the same make and model (laser A and B). But laser B
3920 has an 3000 sheet feeder and laser A doesn't such an option.
3921 Your third printer is an old dot-matrix model for the accounting :-).
3923 If the /usr/local/samba/lib directory (default dir), you will have
3924 5 files to describe all of this.
3926 3 files for the printers (1 by printer):
3927 NTprinter_laser A
3928 NTprinter_laser B
3929 NTprinter_accounting
3930 2 files for the drivers (1 for the laser and 1 for the dot matrix)
3931 NTdriver_printer model X
3932 NTdriver_printer model Y
3934 jfm: I should use this comment for the text file to explain
3935 same thing for the forms BTW.
3936 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
3940 /* Convert generic access rights to printer object specific access rights.
3941 It turns out that NT4 security descriptors use generic access rights and
3942 NT5 the object specific ones. */
3944 void map_printer_permissions(SEC_DESC *sd)
3946 int i;
3948 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3949 se_map_generic(&sd->dacl->ace[i].info.mask,
3950 &printer_generic_mapping);
3954 /****************************************************************************
3955 Check a user has permissions to perform the given operation. We use the
3956 permission constants defined in include/rpc_spoolss.h to check the various
3957 actions we perform when checking printer access.
3959 PRINTER_ACCESS_ADMINISTER:
3960 print_queue_pause, print_queue_resume, update_printer_sec,
3961 update_printer, spoolss_addprinterex_level_2,
3962 _spoolss_setprinterdata
3964 PRINTER_ACCESS_USE:
3965 print_job_start
3967 JOB_ACCESS_ADMINISTER:
3968 print_job_delete, print_job_pause, print_job_resume,
3969 print_queue_purge
3971 ****************************************************************************/
3972 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3974 SEC_DESC_BUF *secdesc = NULL;
3975 uint32 access_granted;
3976 NTSTATUS status;
3977 BOOL result;
3978 char *pname;
3979 TALLOC_CTX *mem_ctx = NULL;
3980 extern struct current_user current_user;
3982 /* If user is NULL then use the current_user structure */
3984 if (!user)
3985 user = &current_user;
3987 /* Always allow root or printer admins to do anything */
3989 if (user->uid == 0 ||
3990 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3991 return True;
3994 /* Get printer name */
3996 pname = PRINTERNAME(snum);
3998 if (!pname || !*pname) {
3999 errno = EACCES;
4000 return False;
4003 /* Get printer security descriptor */
4005 if(!(mem_ctx = talloc_init())) {
4006 errno = ENOMEM;
4007 return False;
4010 nt_printing_getsec(mem_ctx, pname, &secdesc);
4012 if (access_type == JOB_ACCESS_ADMINISTER) {
4013 SEC_DESC_BUF *parent_secdesc = secdesc;
4015 /* Create a child security descriptor to check permissions
4016 against. This is because print jobs are child objects
4017 objects of a printer. */
4019 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
4021 /* Now this is the bit that really confuses me. The access
4022 type needs to be changed from JOB_ACCESS_ADMINISTER to
4023 PRINTER_ACCESS_ADMINISTER for this to work. Something
4024 to do with the child (job) object becoming like a
4025 printer?? -tpot */
4027 access_type = PRINTER_ACCESS_ADMINISTER;
4030 /* Check access */
4032 map_printer_permissions(secdesc->sec);
4034 result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
4035 &access_granted, &status);
4037 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
4039 talloc_destroy(mem_ctx);
4041 if (!result)
4042 errno = EACCES;
4044 return result;
4047 /****************************************************************************
4048 Check the time parameters allow a print operation.
4049 *****************************************************************************/
4051 BOOL print_time_access_check(int snum)
4053 NT_PRINTER_INFO_LEVEL *printer = NULL;
4054 BOOL ok = False;
4055 time_t now = time(NULL);
4056 struct tm *t;
4057 uint32 mins;
4059 if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
4060 return False;
4062 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
4063 ok = True;
4065 t = gmtime(&now);
4066 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
4068 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
4069 ok = True;
4071 free_a_printer(&printer, 2);
4073 if (!ok)
4074 errno = EACCES;
4076 return ok;
4079 #if 0 /* JERRY - not used */
4080 /****************************************************************************
4081 Attempt to write a default device.
4082 *****************************************************************************/
4084 WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
4086 NT_PRINTER_INFO_LEVEL *printer = NULL;
4087 WERROR result;
4090 * Don't bother if no default devicemode was sent.
4093 if (printer_default->devmode_cont.devmode == NULL)
4094 return WERR_OK;
4096 result = get_a_printer(&printer, 2, lp_servicename(snum));
4097 if (!W_ERROR_IS_OK(result)) return result;
4100 * Just ignore it if we already have a devmode.
4102 #if 0
4103 if (printer->info_2->devmode != NULL)
4104 goto done;
4105 #endif
4107 * We don't have a devicemode and we're trying to write
4108 * one. Check we have the access needed.
4110 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
4112 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
4113 PRINTER_ACCESS_ADMINISTER) {
4114 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
4115 result = WERR_ACCESS_DENIED;
4116 goto done;
4119 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
4120 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
4121 lp_servicename(snum) ));
4122 result = WERR_ACCESS_DENIED;
4123 /*result = NT_STATUS_NO_PROBLEMO;*/
4124 goto done;
4127 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
4130 * Convert the on the wire devicemode format to the internal one.
4133 if (!convert_devicemode(printer->info_2->printername,
4134 printer_default->devmode_cont.devmode,
4135 &printer->info_2->devmode)) {
4136 result = WERR_NOMEM;
4137 goto done;
4141 * Finally write back to the tdb.
4144 result = mod_a_printer(*printer, 2);
4146 done:
4148 free_a_printer(&printer, 2);
4149 return result;
4151 #endif /* JERRY */